.NET操作XML小结

来源:互联网 发布:知名的中文域名案例 编辑:程序博客网 时间:2024/04/28 08:00

这篇主要讲讲如何使用XmlDocument配合XPath进行XML的操作,有关XmlDocument和XPath的更多信息,请参考MSDN(http://msdn.microsoft.com/zh-cn/library/system.xml.xmldocument(VS.80).aspxhttp://msdn.microsoft.com/zh-cn/library/ms256471(VS.80).aspx)以及 W3C(http://www.w3.org/TR/xpath

        XPath主要的作用是用来查找符合条件的节点的,对于复杂的XML来说那是相当的有用,所以掌握XPath的语法还是非常重要的

        下面举几个简单的例子来说明一下。例如有XML文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Root>
  3.   <NodeTest id="0">1</NodeTest>
  4.   <NodeTest id="1">2</NodeTest>
  5. </Root>

使用如下代码就可以创建该文件:

  1. XmlDocument doc = new XmlDocument();
  2. XmlDeclaration xd = doc.CreateXmlDeclaration("1.0""utf-8"null);
  3. doc.AppendChild(xd);
  4. XmlElement root = doc.CreateElement("Root");
  5. doc.AppendChild(root);
  6. for (int i = 0; i < 2; i++)
  7. {
  8.     XmlElement nodeTest = doc.CreateElement("NodeTest");
  9.     nodeTest.InnerText = Convert.ToString(i + 1);
  10.     XmlAttribute xa = doc.CreateAttribute("id");
  11.     xa.Value = i.ToString();
  12.     nodeTest.Attributes.Append(xa);
  13.     root.AppendChild(nodeTest);
  14. }
  15. doc.Save("e://1.xml");

下面我们来说说如何使用XPath进行查询

如果我要找到id为1的NodeTest的节点,那么我们应该使用如下代码

  1. XmlDocument doc = new XmlDocument();
  2. doc.Load(filePath);
  3. XmlNode node = doc.SelectSingleNode("/Root/NodeTest[@id='1']");

删除节点很简单,调用RemoveChild方法就可以了,例如上面删除找到的节点,那么使用如下代码

  1. node.ParentNode.RemoveChild(node);
  2. doc.Save(filePath);

修改节点的名称,貌似MS没有提供方法,所以一般来说只能先删除在添加

简单的增删改查已经说完了,下面说说带有命名空间的XML的操作

所谓XML的命名空间,有关更详细的信息,请参考MSDN(http://msdn.microsoft.com/zh-cn/library/c1a6xs06(VS.80).aspx

这里主要会用到XmlNamespaceManager这个类,有关这个类的详细信息,请参考MSDN(http://msdn.microsoft.com/zh-cn/library/system.xml.xmlnamespacemanager(VS.80).aspx

假设有如下XML

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Root xmlns="http://www.w3.org">
  3.   <NodeTest id="0">1</NodeTest>
  4.   <NodeTest id="1">2</NodeTest>
  5. </Root>

使用上面的查找代码你会发现node为null,为什么会出现这种情况呢?那就是命名空间在作怪,此时应该使用如下代码来获取节点

  1. XmlDocument doc = new XmlDocument();
  2. doc.Load(filePath);
  3. XmlNamespaceManager nm = new XmlNamespaceManager(doc.NameTable);
  4. nm.AddNamespace("uu""http://www.w3.org");
  5. XmlNode node = doc.SelectSingleNode("/uu:Root/uu:NodeTest[@id='1']", nm);

另外在操作XML的时候,会碰到合并两个XML文档的操作,此时可以利用InnerXml和OuterXml两个属性,直接拼接字符串,这样就避免了过多的节点操作

假设有如下两个XML

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Root>
  3.   <NodeTests>
  4.       <NodeTest id="0">1</NodeTest>
  5.       <NodeTest id="1">2</NodeTest>
  6.   </NodeTests>
  7.   <CombinNode></CombinNode>
  8. </Root>
  1. <Dictrionary>
  2.   <A>
  3.     <Dic name="Aa" />
  4.     <Dic name="Ac" />
  5.     <Dic name="Awa" />
  6.   </A>
  7.   <DDD>
  8.     <Dic name="Ba" />
  9.     <Dic name="Bc" />
  10.     <Dic name="Bz" />
  11.   </DDD>
  12. </Dictrionary>

想要合并后得到如下的XML

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Root>
  3.   <NodeTests>
  4.       <NodeTest id="0">1</NodeTest>
  5.       <NodeTest id="1">2</NodeTest>
  6.   </NodeTests>
  7.   <CombinNode>
  8.       <A>
  9.         <Dic name="Aa" />
  10.         <Dic name="Ac" />
  11.         <Dic name="Awa" />
  12.       </A>
  13.       <DDD>
  14.         <Dic name="Ba" />
  15.         <Dic name="Bc" />
  16.         <Dic name="Bz" />
  17.       </DDD>
  18.   </CombinNode>
  19. </Root>

那么使用如下代码就可以了


  • XmlDocument doc1 = new XmlDocument();
  • doc1.Load("e://1.xml");
  • XmlNode node1 = doc1.SelectSingleNode("/Root/CombinNode");
  • XmlDocument doc2 = new XmlDocument();
  • doc2.Load("e://2.xml");
  • XmlNode node2 = doc2.SelectSingleNode("/Dictrionary");
  • node1.InnerXml = node2.InnerXml;
  • doc1.Save("e://1.xml");
  • 前面讲了如何使用XmlDocument和XPath操作XML,现在来讲讲如何使用序列化的方式来操作XML

            序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。.NET Framework 提供两种序列化技术:二进制序列化和XML、SOAP序列化(引自MSDNhttp://msdn.microsoft.com/zh-cn/library/7ay27kt9(VS.80).aspx

            把对象转换为XML文档的过程称为对象的XML序列化。

        把XML文档恢复为对象的过程称为对象的XML反序列化。

            XML序列化的应该很广泛,典型的有数据的传输或者动态数据的保存或者简单格式的XML操作,提到XML序列化,有个类肯定是跑不掉的,那就是XmlSerializer,这个类可以将对象序列化到 XML 文档中和从 XML 文档中反序列化对象。有关XmlSerializer的更多信息请参考MSDN(http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.xmlserializer(VS.80).aspx

            下面举几个简单的例子来说明下如何使用XmlSerializer来操作XML

     

    假设有如下XML

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <Root>
    3.   <OutputPath></OutputPath>
    4.   <InitialDirectory></InitialDirectory>
    5.   <Configs>
    6.     <Config DisplayName="">
    7.       <UserName></UserName>
    8.       <PassWord></PassWord>
    9.       <Path></Path>
    10.       <ProjectPath></ProjectPath>
    11.     </Config>
    12.     <Config DisplayName="">
    13.       <UserName></UserName>
    14.       <PassWord></PassWord>
    15.       <Path></Path>
    16.       <ProjectPath></ProjectPath>
    17.     </Config>
    18.   </Configs>
    19. </Root>

    我们需要建两个类

    1. [Serializable]
    2. public class Config
    3. {
    4.     [NonSerialized]
    5.     private string displayName = String.Empty;
    6.     [XmlAttribute("DisplayName")]
    7.     public string DisplayName
    8.     {
    9.         get { return displayName; }
    10.         set { displayName = value; }
    11.     }
    12.     [NonSerialized]
    13.     private string userName = String.Empty;
    14.     [XmlElement("UserName")]
    15.     public string UserName
    16.     {
    17.         get { return userName; }
    18.         set { userName = value; }
    19.     }
    20.     [NonSerialized]
    21.     private string passWord = String.Empty;
    22.     [XmlElement("PassWord ")]
    23.     public string PassWord 
    24.     {
    25.         get { return passWord; }
    26.         set { passWord = value; }
    27.     }
    28.     [NonSerialized]
    29.     private string path = String.Empty;
    30.     [XmlElement("Path")]
    31.     public string Path
    32.     {
    33.         get { return path; }
    34.         set { path = value; }
    35.     }
    36.     [NonSerialized]
    37.     private string projectPath = String.Empty;
    38.     [XmlElement("ProjectPath")]
    39.     public string ProjectPath
    40.     {
    41.         get { return projectPath; }
    42.         set { projectPath = value; }
    43.     }
    44. }
    1. [Serializable]
    2. [XmlRoot("Root")]
    3. [XmlInclude(typeof(Config))]
    4. public class SerializeConfigs
    5. {
    6.     [NonSerialized]
    7.     private string outputPath = String.Empty;
    8.     [XmlElement("OutputPath")]
    9.     public string OutputPath
    10.     {
    11.         get { return outputPath; }
    12.         set { outputPath = value; }
    13.     }
    14.     [NonSerialized]
    15.     private string initialDirectory = String.Empty;
    16.     [XmlElement("InitialDirectory")]
    17.     public string InitialDirectory
    18.     {
    19.         get { return initialDirectory; }
    20.         set { initialDirectory = value; }
    21.     }
    22.     [NonSerialized]
    23.     private List<Config> configs = new List<Config>();
    24.     [XmlArrayItem("Configs"typeof(Config), ElementName = "Config")]
    25.     public List<Config> Configs
    26.     {
    27.         get { return vssConfigs; }
    28.         set { vssConfigs = value; }
    29.     }
    30. }

    对上面的两个类做个简单的说明:

    1、你想执行序列化的类必须声明Serializable属性

    2、在XML序列化中你可以使用NonSerialized或者XmlIgnore属性来决定某个Filed是否被序列化

    3、如果该Filed是XML节点的属性的话,请使用XmlAttribute

    4、通过Attribute可以使类中的字段名称与XML节点名称不一致

     

    好了,准备工作都做完了,下面让我们看看具体的代码吧

    1. private void Serialize()
    2. {
    3.     SerializeConfigs configs = new SerializeConfigs();    
    4.     XmlSerializer mySerializer = new XmlSerializer(typeof(SerializeConfigs));
    5.     StreamWriter myWriter = new StreamWriter(filePath);
    6.     XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
    7.     xmlns.Add(String.Empty, String.Empty);
    8.     mySerializer.Serialize(myWriter, configs, xmlns);
    9.     myWriter.Close();
    10. }
    11. private SerializeConfigs Deserialize()
    12. {
    13.     XmlSerializer mySerializer = new XmlSerializer(typeof(SerializeConfigs));
    14.     FileStream myFileStream = new FileStream(filePath, FileMode.Open);
    15.     SerializeConfigs configs = mySerializer.Deserialize(myFileStream) as SerializeConfigs;
    16.     myFileStream.Close();
    17.     return configs;
    18. }

    这个例子只是最简单的一种,有兴趣的朋友可以参考MSDN的System.Xml.Serialization命名空间下的成员,有很多Attribute供我们使用(http://msdn.microsoft.com/en-us/library/system.xml.serialization.aspx

    当然如果你觉得XmlSerializer不能满足你的要求的话,你可以继承XmlSerializer、XmlSerializationReader以及XmlSerializationWriter,实现自己的XmlSerializer

    原创粉丝点击