代码之家  ›  专栏  ›  技术社区  ›  user726720

无条件遍历XML

  •  -1
  • user726720  · 技术社区  · 6 年前

    我有以下XML结构我包含很多节点 <PName> . 我需要做的是运行一个xpath查询match a condition提取一些数据。运行到下一个节点测试条件,然后返回到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.
     } 
    

    我真的不知道如何在没有条件和想法的情况下像这样有力地导航。

    2 回复  |  直到 6 年前
        1
  •  1
  •   zx485 potemkin    6 年前

    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访问它。例如,要获得 category 下一个的属性值 pNeNe 具有 classification 属性的值为“食物”,您可以在 foreach 循环:

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

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

        2
  •  0
  •   jdweng    6 年前

    尝试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();
    
    
            }
        }
    }