C# 异常的 xml 分析

本文关键字:分析 xml 异常 | 更新日期: 2023-09-27 17:55:48

我必须将一个xml文件解析为另一个严格定义的文件。原始文件如下所示:

<Data>
    <Client>
        <id>ID1</id>
        <Details>
            <detail1>1</detail1>
            <detail2>2</detail2>
        </Details>
        <Details>
            <detail1>3</detail1>
            <detail2>4</detail2>
        </Details>
    </Client>
    <Client>
        <id>ID2</id>
        <Details>
            <detail1>1</detail1>
            <detail2>2</detail2>
        </Details>
    </Client>
    <Client>
        <id>ID3</id>
        <Details>
            <detail1>1</detail1>
            <detail2>2</detail2>
        </Details>
    </Client>
</Data>

基本上我需要做的就是用不同的节点名称重写文件并解析节点内的一些数据,结构本身保持不变。
现在我有:

var ClientNodes = xml.SelectNodes("//Client");
for (int i = 0; i < ClientNodes.Count; i++)
{
    // this iterates through all Client nodes
    var DetailsNodes = xml.SelectNodes("//Details");
    for (int j = 0; j < DetailsNodes.Count; j++)
    {
        // this iterates through ALL "//Details" nodes and that's the problem
    }
}

如果我只是遍历如上所示的"详细信息"节点,则会收到类似以下内容的内容:

<Client>
    <id>ID1</id>
    <Details>
        <detail1>1</detail1>
        <detail2>2</detail2>
    </Details>
    <Details>
        <detail1>3</detail1>
        <detail2>4</detail2>
    </Details>
    <Details>
        <detail1>1</detail1>
        <detail2>2</detail2>
    </Details>
    <Details>
        <detail1>1</detail1>
        <detail2>2</detail2>
    </Details>

我不知道如何处理这个问题。主要问题是某些客户机节点可以有 2 个或更多详细信息节点。

最好的解决方案(我认为)是找到一种方法来遍历单个客户端节点中的所有节点,但我不知道这是否可能(这就是我决定在这里写我的问题的原因),加上我必须处理的文件在单个 Details 节点中有 ~20 个节点。

C# 异常的 xml 分析

强烈建议使用LINQ to XML而不是XPath。(当然,您可以使用XPath - 但它的可读性较差。你只需要使用ClientNodes[i].SelectNodes("Details")

var xml = XDocument.Load(...);
foreach (var client in xml.Root.Elements("Client"))
{
    // Do whatever you need to here
    foreach (var detail in client.Elements("Details"))
    {
        // Do whatever you need to here
    }
}

LINQ to XML是一个很棒的XML API,非常值得学习...

开头

//使搜索表达式相对于文档根目录。您希望改用.//Details - 请参阅 XPath 表达式的上下文

使用双正斜杠 (//) 的表达式表示 可以包含零级或多个层次结构的搜索。当这个 运算符出现在模式的开头,上下文为 相对于文档的根目录。例如,以下表达式引用当前文档中任意位置的所有元素:

//author

.//前缀表示上下文从当前上下文指示的层次结构中的级别开始。

我最近做了一些非常相似的事情,我找到的最佳解决方案是下面的代码:

foreach (XmlElement element0 in xml.GetElementsByTagName("Client")
{
     // your code
    foreach (XmlElement element1 in client.GetElementsByTagName("Details")
    {
         // your code
    }
}

基本上,这段代码要做的是遍历客户端中名为"Details"的每个节点,然后它将移动到下一个客户端并重复该过程。

让我们使用这段代码

string s = "<Data><Client><id>ID1</id><Details><detail1>1</detail1><detail2>2</detail2></Details><Details><detail1>3</detail1><detail2>4</detail2></Details></Client><Client><id>ID2</id><Details><detail1>1</detail1><detail2>2</detail2></Details></Client><Client><id>ID3</id><Details><detail1>1</detail1><detail2>2</detail2></Details></Client></Data>";
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(s);
//Store nodes in variables
XmlNodeList Client, Details;
//Get all clients
Client = xDoc.SelectNodes("/Data/Client");
foreach (XmlNode cn in Client)
{
    //Get all Details parents
    Details = cn.SelectNodes("Details");
    foreach (XmlNode dn in Details)
    {
        //Get all "sub" detail of parents, or details values
        foreach (XmlNode n in dn.ChildNodes)
        {
            Console.WriteLine(n.InnerText);
        }
    }
}

您所做的错误是始终使用高级 XML 元素