1、xmlns为名称空间,读取时,需指定XmlNamespaceManager,否则无法正确读取。
2、当有名称空间时,CreateElement需设置namespace参数需设置父节点的名称空间,如 _xmlDoc.CreateElement(childNodeName, node.NamespaceURI),否则会出现xmlns=""情况。
结合之前用xml文件的各种情况,写了个xml操作类,未测试全部函数
using System;
using System.Data;
using System.Configuration;
using System.Collections;
//引用命名空间
using System.Xml;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
namespace CreateNhibernateSourceCode
{
/// <summary>
/// XmlOp类提供对XML数据库的读写
/// </summary>
public class XMLHelper:IDisposable
{
#region 私有成员
//声明一个XmlDocument空对象
protected XmlDocument _xmlDoc = new XmlDocument();
/// <summary>
/// XML文件名称空间
/// </summary>
XmlNamespaceManager _nsMgr;
/// <summary>
/// 原文件路径
/// </summary>
string _filePath;
#endregion
#region 公共属性
/// <summary>
/// 获取XML文件完整路径
/// </summary>
public string FilePath
{
get { return this._filePath; }
}
#endregion
#region 构造析构
/// <summary>
/// 构造函数,导入Xml文件
/// </summary>
/// <param name="filePath">文件绝对路径</param>
/// <param name="namespacename">顶级节点xmlns内容,名称空间名称,格式:http://schemas.microsoft.com/developer/msbuild/2003 </param>
public XMLHelper(string filePath, string namespacename = null)
{
try
{
_xmlDoc.Load(filePath); //载入Xml文档
this._filePath = filePath;
if (!string.IsNullOrEmpty(namespacename))
{
_nsMgr = new XmlNamespaceManager(_xmlDoc.NameTable);
_nsMgr.AddNamespace("ns", namespacename);
}
}
catch (System.Exception ex)
{
throw ex;
}
}
/// <summary>
/// 析构函数
/// </summary>
public void Dispose()
{
_xmlDoc = null; //释放XmlDocument对象
}
#endregion
#region 保存
/// <summary>
/// 另存为
/// </summary>
/// <param name="filePath">文件虚拟路径</param>
public void Save(string filePath)
{
try
{
_xmlDoc.Save(filePath);
}
catch (System.Exception ex)
{
throw ex;
}
}
/// <summary>
/// 保存文
/// </summary>
public void Save()
{
try
{
_xmlDoc.Save(this._filePath);
}
catch (System.Exception ex)
{
throw ex;
}
}
#endregion
#region 获取单节点
/// <summary>
/// 获取无重名单个节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <returns></returns>
public XmlNode SelectSingleNode(string xpath)
{
if (_nsMgr == null)
return _xmlDoc.SelectSingleNode(xpath);
else
{
string[] nodes = xpath.Split('/');
StringBuilder sbNode = new StringBuilder();
foreach (string node in nodes)
{
sbNode.Append(string.Format("/ns:{0}", node));
}
return _xmlDoc.SelectSingleNode(sbNode.ToString(), _nsMgr);
}
}
/// <summary>
/// 获取单个节点,重名时用,用子节点确定父节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="level">返回父节点级数,默认一级</param>
/// <returns></returns>
public XmlNode SelectParentSingleNode(string xpath,int level=1)
{
try
{
XmlNode parentNode = this.SelectSingleNode(xpath);
if (parentNode != null)
{
for (int i = 0; i < level; i++)
{
parentNode = parentNode.ParentNode;
}
return parentNode;
}
else
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 获取节点列表
/// <summary>
/// 获取不重名的节点孩子集合
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <returns></returns>
public XmlNodeList SelectChildNodeList(string xpath)
{
try
{
XmlNode parentNode = this.SelectSingleNode(xpath);
if (parentNode!=null && parentNode.HasChildNodes)
return parentNode.ChildNodes;
else
return null;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 获取节点孩子集合,重名时用,通过子节点确定父节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="level">返回父节点级数,默认一级</param>
/// <returns></returns>
public XmlNodeList SelectChildNodeListOfParent(string xpath, int level=1)
{
try
{
XmlNode parentNode = this.SelectSingleNode(xpath);
if (parentNode != null)
{
for (int i = 0; i < level; i++)
{
parentNode = parentNode.ParentNode;
}
return parentNode.ChildNodes;
}
else
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 获取节点数据集
/// <summary>
/// 根据Xml文件的节点路径,返回一个DataSet数据集
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <returns></returns>
public DataSet GetDataSet(string xpath)
{
DataSet ds = new DataSet();
try
{
System.IO.StringReader read=new System.IO.StringReader(this.SelectSingleNode(xpath).OuterXml);
ds.ReadXml(read); //利用DataSet的ReadXml方法读取StringReader文件流
read.Close();
}
catch(Exception ex)
{
throw ex;
}
return ds;
}
#endregion
#region 查询节点属性
/// <summary>
/// 返回无重名节点属性值
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="attributeName">属性名称</param>
/// <returns></returns>
public string SelectAttribute(string xpath, string attributeName)
{
try
{
return this.SelectSingleNode(xpath).Attributes[attributeName].Value;
}
catch(Exception ex)
{
throw ex;
}
}
/// <summary>
/// 返回节点属性值,重名时用,用子节点确定父节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="attributeName">属性名称</param>
/// <param name="level">返回父节点级数,默认一级</param>
/// <returns></returns>
public string SelectParentNodeAttribute(string xpath, string attributeName,int level=1)
{
try
{
return this.SelectParentSingleNode(xpath,level).Attributes[attributeName].Value;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 查询节点InnerText
/// <summary>
/// 返回无重名节点InnerText
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <returns></returns>
public string SelectInnerText(string xpath)
{
try
{
return this.SelectSingleNode(xpath).InnerText;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 返回节点InnerText,重名时用,通过子节点确定父节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="level">返回父节点级数,默认一级</param>
/// <returns></returns>
public string SelectParentNodeInnerText(string xpath, int level = 1)
{
try
{
return this.SelectParentSingleNode(xpath,level).InnerText;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 根据属性值查询节点
/// <summary>
/// 查询具有某个属性名称和值的特定路径节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="attributeName">属性Name</param>
/// <param name="attributeValue">属性Value</param>
/// <returns>存在返回该节点,不存在返回空</returns>
public XmlNode FindNode(string xpath, string attributeName, string attributeValue)
{
try
{
XmlNode node = this.SelectSingleNode(xpath);
if (node != null)
{
node = node.ParentNode;
XmlNodeList childNodes = node.ChildNodes;
string nodeName = xpath.Substring(xpath.LastIndexOf('/') + 1);
foreach (XmlNode childNode in childNodes)
{
if (childNode.Name.Equals(nodeName) && childNode.Attributes[attributeName].Value.Equals(attributeValue))
return childNode;
}
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 根据InnerText查询节点
/// <summary>
/// 查询具有某个InnerText的特定路径节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="innerText">InnerText值</param>
/// <returns>存在返回该节点,不存在返回空</returns>
public XmlNode FindNode(string xpath, string innerText)
{
try
{
XmlNode node = this.SelectSingleNode(xpath);
if (node != null)
{
node = node.ParentNode;
XmlNodeList childNodes = node.ChildNodes;
string nodeName = xpath.Substring(xpath.LastIndexOf('/') + 1);
foreach (XmlNode childNode in childNodes)
{
if (childNode.Name.Equals(nodeName) && childNode.InnerText.Equals(innerText))
return childNode;
}
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 更新或新增节点InnerText
/// <summary>
/// 更新或新增某个节点的InnerText
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="innerText">InnerText值</param>
public void SaveOrUpdate(string xpath, string innerText)
{
try
{
XmlNode node = this.SelectSingleNode(xpath);
if (node == null)
{
int lastIndex = xpath.LastIndexOf('/');
string parentNodePath = xpath.Substring(0, lastIndex);
node = this.SelectSingleNode(parentNodePath);
string childNodeName = xpath.Substring(lastIndex + 1);
if (node != null)
{
XmlElement objChildNode = _xmlDoc.CreateElement(childNodeName); //创建XmlElement对象
node.AppendChild(objChildNode);
objChildNode.InnerText = innerText;
}
}
else
node.InnerText = innerText;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 更新无重名节点InnerText
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="Content">InnerText</param>
/// <returns></returns>
public bool UpdateInnerText(string xpath, string innerText)
{
try
{
XmlNode node = this.SelectSingleNode(xpath);
if (node != null)
node.InnerText = innerText;
else
return false;
return true;
}
catch(Exception ex)
{
throw ex;
}
}
#endregion
#region 批量更新节点InnerText
/// <summary>
/// 批量添加节点及InnerText,先删除父节点所有孩子
/// 如果无孩子节点,则寻找第一复合父节点名称的节点创建孩子节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="innerTexts">InnerText集合</param>
/// <param name="level">返回父节点级数,默认一级</param>
public void UpdateInnerTexts(string xpath, string[] innerTexts,int level=1)
{
try
{
XmlNode node = this.SelectParentSingleNode(xpath, level);
if (node == null) node = this.SelectSingleNode(xpath.Substring(0, xpath.LastIndexOf('/')));
if (node != null)
{
this.UpdateInnerTexts(node, xpath.Substring(xpath.LastIndexOf('/') + 1), innerTexts);
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 批量添加节点及InnerText,先删除父节点所有孩子
/// </summary>
/// <param name="parentNode">父节点</param>
/// <param name="childNodeName">孩子节点Name</param>
/// <param name="innerTexts">InnerText值</param>
public void UpdateInnerTexts(XmlNode parentNode,string childNodeName, string[] innerTexts)
{
if (parentNode != null)
{
if (parentNode.HasChildNodes)
{
parentNode.RemoveAll();
}
foreach (string innerText in innerTexts)
{
XmlElement objChildNode = _xmlDoc.CreateElement(childNodeName); //创建XmlElement对象
parentNode.AppendChild(objChildNode);
objChildNode.InnerText = innerText;
}
}
}
#endregion
#region 更新或新增节点属性
/// <summary>
/// 更新或新增某个节点的属性们
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="keyName">主键Name</param>
/// <param name="keyValue">主键值</param>
/// <param name="attributeNames">属性名称集合</param>
/// <param name="attributeValues">属性值集合</param>
public void SaveOrUpdate(string xpath, string keyName,string keyValue,string[] attributeNames,string[] attributeValues)
{
try
{
XmlNode node = this.FindNode(xpath, keyName, keyValue);
if (node == null)
{
int lastIndex = xpath.LastIndexOf('/');
string parentNodePath = xpath.Substring(0, lastIndex);
node = this.SelectSingleNode(parentNodePath);
string childNodeName = xpath.Substring(lastIndex + 1);
if (node != null)
{
XmlElement objChildNode = _xmlDoc.CreateElement(childNodeName); //创建XmlElement对象
node.AppendChild(objChildNode);
for (int i = 0; i < attributeValues.Length; i++)
{
objChildNode.SetAttribute(attributeNames[i], attributeValues[i]);
}
}
}
else
{
for (int i = 0; i < attributeValues.Length; i++)
{
node.Attributes[attributeNames[i]].Value = attributeValues[i];
}
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 新增带属性的节点,不考虑父节点是否存在
/// </summary>
/// <param name="xpath"></param>
/// <param name="attributeNames"></param>
/// <param name="attributeValues"></param>
public XmlNode InsertNode(string xpath, string[] attributeNames, string[] attributeValues)
{
try
{
int lastIndex = xpath.LastIndexOf('/');
XmlNode node = this.SelectParentSingleNode(xpath);
string childNodeName = xpath.Substring(lastIndex + 1);
if (node != null)
{
XmlElement objChildNode = _xmlDoc.CreateElement(childNodeName,node.NamespaceURI); //创建XmlElement对象
node.AppendChild(objChildNode);
for (int i = 0; i < attributeValues.Length; i++)
{
objChildNode.SetAttribute(attributeNames[i], attributeValues[i]);
}
return (XmlNode)objChildNode;
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 新增带属性的节点,不考虑父节点是否存在
/// </summary>
/// <param name="xpath"></param>
/// <param name="attributeNames"></param>
/// <param name="attributeValues"></param>
public void InsertNode(XmlNode node,string childNodeName, string[] attributeNames, List<List<string>> attributeValues)
{
try
{
foreach (List<string> values in attributeValues)
{
XmlElement objChildNode = _xmlDoc.CreateElement(childNodeName, node.NamespaceURI); //创建XmlElement对象
node.AppendChild(objChildNode);
for (int i = 0; i < attributeNames.Length; i++)
{
objChildNode.SetAttribute(attributeNames[i], values[i]);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 批量更新节点属性和属性值
/// <summary>
/// 批量添加节点及InnerText,先删除父节点所有孩子
/// 如果无孩子节点,则寻找第一复合父节点名称的节点创建孩子节点
/// </summary>
/// <param name="xpath">格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="attributeNames">属性名称集合</param>
/// <param name="attributeNames">属性值集合</param>
/// <param name="level">返回父节点级数,默认一级</param>
public void UpdateAttributes(string xpath, string[] attributeNames,string[] attributeValues, int level = 1)
{
try
{
XmlNode node = this.SelectParentSingleNode(xpath, level);
if (node == null) node = this.SelectSingleNode(xpath.Substring(0, xpath.LastIndexOf('/')));
if (node != null)
{
this.UpdateAttributes(node, xpath.Substring(xpath.LastIndexOf('/') + 1), attributeNames, attributeValues);
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 批量添加节点及InnerText,先删除父节点所有孩子
/// </summary>
/// <param name="parentNode">父节点</param>
/// <param name="childNodeName">孩子节点Name</param>
/// <param name="attributeNames">属性名称集合</param>
/// <param name="attributeNames">属性值集合</param>
public void UpdateAttributes(XmlNode parentNode, string childNodeName, string[] attributeNames, string[] attributeValues)
{
if (parentNode != null)
{
if (parentNode.HasChildNodes)
{
parentNode.RemoveAll();
}
for (int i = 0; i < attributeNames.Length;i++ )
{
XmlElement objChildNode = _xmlDoc.CreateElement(childNodeName); //创建XmlElement对象
parentNode.AppendChild(objChildNode);
objChildNode.SetAttribute(attributeNames[i], attributeValues[i]);
}
}
}
#endregion
#region 节点转换为模型
/// <summary>
/// 节点转换为模型实例
/// </summary>
/// <typeparam name="T">模型类型</typeparam>
/// <param name="node">节点</param>
/// <param name="names">字段名称集合</param>
/// <returns></returns>
public T Convert<T>(XmlNode node,string[] names) where T: new()
{
T t = new T();
Type type=t.GetType();
foreach (string name in names)
{
PropertyInfo propertyInfo = type.GetProperty(name);
if (propertyInfo != null)
{
propertyInfo.SetValue(t, node.Attributes[name].Value, null);
}
}
return t;
}
/// <summary>
/// 保存实体为带属性的节点
/// </summary>
/// <param name="entity">实体实例</param>
/// <param name="xpath">包含最底层节点名称,格式:顶级节点名称/下级节点名称/下级节点名称</param>
/// <param name="keyName">主键属性名称</param>
/// <param name="keyValue">主键属性值</param>
/// <param name="atrributeMames">属性名称集合,包含主键</param>
public void SaveNode(object entity, string xpath, string keyName, string keyValue, string[] atrributeMames)
{
List<string> atrributeValues = new List<string>();
Type type = entity.GetType();
foreach (string name in atrributeMames)
{
PropertyInfo property = type.GetProperty(name);
if (property != null)
{
atrributeValues.Add(System.Convert.ToString(property.GetValue(entity, null)));
}
}
this.SaveOrUpdate(xpath, keyName, keyValue, atrributeMames, atrributeValues.ToArray());
}
#endregion
}
}