使用包含多个节点的 C# 修改 XML 文件

Amending an XML file using C# containing multiple nodes

我正在尝试在 Visual Studio 2017 年开发一个简单的 c# 程序,它循环遍历 XML 文件,并将根据文件中的 'type' 编号修改某些节点。每个 'code' 都有不同的类型编号。

例如,如果类型编号 = 4,则将附加信息添加到节点 'name'。例如末尾的姓氏。

但是我不希望它修改出现在类型 5 下的节点 'name'。我查看了其他问题和答案,但这些问题和答案并没有处理文件中的多个后代!

<?xml version="1.0" encoding="utf-8"?>
<testing>
    <names>
        <name>
            <code>0000</code>
            <type>4</type>
            <steps>
                <nStep>
                    <name>John</name>
                </nStep>
            </steps>
        </name>
        <name>
            <code>1111</code>
            <type>5</type>
            <steps>
                <nStep>
                    <name>Paul</name>
                </nStep>
            </steps>
        </name>
    </names>
</testing>

您可以使用 Linq to XML 来执行此操作。

根据您需要的灵活性,这里有几种不同的方法。首先,使用XPath(需要参考System.Xml.XPath获取相关的扩展方法)。在这里,您可以使用 XPath 查询表达式过滤要更改的节点,例如,在这种情况下,我们仅迭代类型为“4”的节点:

// you can load xml from string or however you have it
var xDoc = XDocument.Load(@"c:\temp\myxml.xml"); 

foreach (var nameElement in xDoc.XPathSelectElements("//testing/names/name[type='4']"))
{
    nameElement
        .Descendants("name")
        .Single()
        .Value += " Smith";
}

或者,此方法将迭代父元素 names 下的所有 name 元素,并允许您打开 type 元素的值以执行每种情况下的不同操作:

// select the name elements, and parse the type into an integer (optional, you can 
// switch on type as a string if you prefer).
var nameElements = xDoc
    .Element("testing")
    .Element("names")
    .Elements("name")
    .Select(name => new { Type = int.Parse(name.Element("type").Value), Element = name });

// iterate on each name element
foreach (var nameElement in nameElements)
{
    // check the type
    switch (nameElement.Type)
    {
        case 4:
            nameElement
                .Element
                .Descendants("name") // filter to name elements under the parent name element
                .Single() // we only expect one
                .Value += " Smith"; // append a last name
            break;
        default:
            continue; // don't do anything
    }
}