【问题标题】:Traversing XML without conditions无条件遍历 XML
【发布时间】:2018-12-21 15:38:04
【问题描述】:

我有以下 XML 结构,其中包含很多节点 <PName>。我需要做的是运行 Xpath 查询匹配条件提取一些数据。运行到下一个节点测试条件,然后返回 XPath 查询并继续该过程

这是我的 XML:

<?xml version="1.0"?>
<PatientDetailsXML>
  <PList>
    <PName type="Patient">
      <properties>
        <Room bedType="Auto"/>
        <PName title="Joe Beom" PId="1234">
          <Details>
            <classification classification="paymenttype" category="Wallet"/>
            <classification classification="Humor" category="None"/>
            <classification classification="Food" category="Fruit"/>
          </Details>
        </PName>
      </properties>
      <childEvents>
      </childEvents>
    </PName>
    <PName type="Patient">
      <properties>
        <Room bedType="Auto"/>
        <PName title="John Bair" PId="1234">
          <Details>
            <classification classification="paymenttype" category="Found"/>
            <classification classification="Humor" category="None"/>
            <classification classification="Food" category="Fruit"/>
          </Details>
        </PName>
      </properties>
      <childEvents>
      </childEvents>
    </PName>
  </PList>
</PatientDetailsXML>

这是我的代码:

var query = @"//PName[.//PName[Details/classification[@classification='paymenttype' and @category='Wallet']]]";   
foreach (XmlNode n in docs.SelectNodes(query))
{
    var titlelink = n.SelectSingleNode(".//PName/@title");
    var title = titlelink.Value;
    var bedlink = n.SelectSingleNode(".//Room/@bedType");
    var bed = bedlink.Value;
    // Here I want to run to the very next node <PName> and do 
    // some test's such as `classification='paymenttype' and 
    // @category='Wallet'`, if not true insert some data in XML
    // jump back to the XPATH node (where query was working at 
    // and continue the iteration). 
    // If it matches I fetch some data.
 } 

我真的不知道如何在没有条件的情况下像这样强制导航,我们将不胜感激。

【问题讨论】:

  • 这是一个令人困惑的问题。你的标题说没有条件。你的第一段说它必须满足条件,你以“没有条件”结束。在我看来,如果没有任何类型的分支代码(条件),编写任何代码都非常困难。

标签: c# xml xpath


【解决方案1】:

您的 XPath 表达式不正确。
因此,将您的 C# 代码及其 XPath 表达式更改为

var query = @"//PName[Details/classification[@classification='paymenttype' and @category='Wallet']]"; 
// This query will select PName nodes with a condition
foreach (XmlNode n in docs.SelectNodes(query))
{
    var titlelink = n.SelectSingleNode("@title");
    var title = titlelink.Value;
    var bedlink = n.SelectSingleNode("../Room/@bedType");
    var bed = bedlink.Value;
}

这应该会让你更接近你的目标。


如果您想从另一个 PName 元素中检索节点/值,您也可以使用 XPath 访问它。例如,要获取下一个PName 元素的category 属性值,该元素的classification 属性值为“Food”,您可以在foreach 循环中使用此XPath 表达式:

var foodlink = n.SelectSingleNode("ancestor::PName/following-sibling::PName/properties/PName/Details/classification[@classification='Food']/@category");
var food = foodlink.Value;

它的输出应该是“水果”。

【讨论】:

  • 谢谢,但知道如何遍历 xml,例如跳转到下一个节点
  • 您使用foreach 循环遍历XML。它遍历所有满足指定条件的PName 元素。
  • 是的,这是真的,但是在 for each 循环的第一轮迭代中,我需要跳转到下一个节点测试一些东西并返回到 foreach 循环并继续
  • 我用一个解决方案扩展了我的答案以访问下一个 PName 元素。
【解决方案2】:

试试 xml linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement plist = doc.Descendants("PList").FirstOrDefault();

            List<XElement> pName = plist.Elements("PName").ToList();

            var results = pName.Select(x => new {
                bedType = (string)x.Descendants("Room").FirstOrDefault().Attribute("bedType"),
                name = (string)x.Descendants("PName").FirstOrDefault().Attribute("title"),
                id = (string)x.Descendants("PName").FirstOrDefault().Attribute("PId"),
            }).ToList();


        }
    }
}

【讨论】:

    猜你喜欢
    • 2014-03-11
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多