复制节点并将其另存为新的 XML 文件 C#

本文关键字:XML 文件 另存为 节点 复制 | 更新日期: 2023-09-27 18:30:26

我是新手,这是我关于stackoverflow的第一个问题,所以请耐心等待。

我有以下 xml 文件

<?xml version="1.0" encoding="utf-8"?>
<items>
 <superitem>
  <item id="10" name="Ten"
        description="This is number ten">
    <attribute name="weight" value="1" />
    <attribute name="capacity" value="80" />
  </item>
  <item id="20" name="Twenty"
        description="This is might be number twenty">
    <attribute name="weight" value="1" />
    <attribute name="opaque" value="11" />
    <uncertain>
      <uncertainity name="might" level="Eighty Twenty."/>
    </uncertain>
  </item>
 </superitem>
</items>

在代码中,我正在尝试复制id = 20的节点

newItem.SelectSingleNode("/items/superitem/item[@id='20']")

并将该唯一节点保存到另一个 xml 文件中。所以我正在尝试获取这样的 xml

<?xml version="1.0" encoding="utf-8"?>
<items>
 <superitem>
  <item id="20" name="Twenty"
        description="This is might be number twenty">
    <attribute name="weight" value="1" />
    <attribute name="opaque" value="11" />
    <uncertain>
      <uncertainity name="might" level="Eighty Twenty."/>
    </uncertain>
  </item>
 </superitem>
</items>

我尝试将该节点导入该 xml 的最后一个子项之后的 xml 文件,我可以这样做。如果我需要仅使用该节点创建新的 xml 文件,该怎么办?输出 xml 与我上面提到的完全相同??

复制节点并将其另存为新的 XML 文件 C#

使用 XElement (XLinq) 要容易得多。

XElement oldDoc = XElement.Load(filename1);
//XElement items = oldDoc.XPathSelectElements("/items/superitem/item[@id='20']");
//XElement newDoc = new XElelement("items", new XElement("superitem", items));
// Because of using an XElement as toplevel (and not XDocumet), 
// the XPath has to start lower. And a Singular result is more to the point.
var item = doc.XPathSelectElement("//superitem/item[@id='20']");
XElement newDoc = new XElelement("items", new XElement("superitem", item));
newDoc.Save(fileName2);

使用 linq to xml

var xDoc = XDocument.Load(fname);
foreach (var item in xDoc.XPathSelectElements("/items/superitem/item[@id!='20']"))
    item.Remove();
xDoc.Save(fname);

一个看起来很糟糕但有效的 C#/.NET 2.0 解决方案,如果有人需要它:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filename); // path to the .xml file
XmlNode selectedNode = xmlDoc.SelectSingleNode("/items/superitem/item[@id='20']");
XmlDocument newXmlDoc = new XmlDocument();
XmlDeclaration declaration = newXmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
newXmlDoc.AppendChild(declaration);
XmlNode itemsNode = newXmlDoc.CreateElement("items");
newXmlDoc.AppendChild(itemsNode);
XmlNode superitemNode = newXmlDoc.CreateElement("superitem");
itemsNode.AppendChild(superitemNode);
XmlNode itemNode = newXmlDoc.ImportNode(selectedNode, true);
superitemNode.AppendChild(itemNode);
newXmlDoc.Save(outputFileName); // name of the new .xml file

如果您不需要史前代码,建议使用其他答案。 ;)

一个快速的解决方案是删除除要保留的元素之外的所有元素,然后保存到新文件:

    var xml = XDocument.Load(@"c:'temp'input.xml");
    xml.Element("items")
       .Element("superitem")
       .Elements()
       .Where(x => x.Attribute("id").Value != "20")
       .Remove();
    xml.Save(@"c:'temp'output.xml");

请注意,这不会对缺失的节点等执行任何防御性检查。它假设它将始终获得您在示例中显示的内容 - 通常不是生产代码的安全假设。

Linq to xml是惊人的。

下面是一些示例代码,用于获取超级项并将其存储在新文件中。

 //Load the current xml
        var Document = new XDocument();
        Document = XDocument.Load(AppDomain.CurrentDomain.BaseDirectory + @"MyXmlFile.xml");

        //Get the Superitem based on id attribute (you'll want to do some checks to make sure that the xml has the relevent <superitem> node
        XElement superitem = Document.Root.Element("superitem").Elements().FirstOrDefault(x => (int?)x.Attribute("id") == 10);
        //check a superitem with the id was found
        if (superitem != null)
        {
            //Create New Document:
            var newDocument = new XDocument();
            newDocument.Declaration =
                new XDeclaration("1.0", "utf-8", null);
            //Create Root node (items)
            XElement root = new XElement("items");
            newDocument.Add(root);
            //Add the super item to the root.
            root.Add(new XElement("superitem", superitem));

            //Save
            newDocument.Save(AppDomain.CurrentDomain.BaseDirectory + @"SuperItem.xml");
        }