如何为 XML 创建 XPath?

Posted

技术标签:

【中文标题】如何为 XML 创建 XPath?【英文标题】:How To Create XPath for XML? 【发布时间】:2013-04-27 03:08:49 【问题描述】:

我有一个 Xml 文件,我想在其中制作基于 XPath 的过滤器。我尝试了很多例子,它们都没有帮助毫无疑问我做错了。 我是 XPath 的新手,请帮助我找到解决方案。

<PeopleBatch Counter="3">
<Citriz ID="1d9a88fe-f9cc-4add-b6d1-01e41c561bfb" mVersion="1.0.0" mSequence="1" pVersion="0.0.1" xmlns="http://Citriz/Schemas">
    <People Action="U" Status="CD" PeopleID="1" PeopleShortName="Billy" PeopleLongName="Billy Smith" PeopleTypeCode="Commercial" CountryCode="USA" PeopleStatus="Current">
            <PeopleRole Action="U" Status="CD" ID="1" CustomerRoleShortName="Billy" CustomerRoleLongName="Billy Smith" TypeCode="OUTS">
                    <SendRole RoleType="N" ActiveRole="Y"/>
            </PeopleRole>
    </People>
</Citriz>
<Citriz ID="1d9a88fe-f9cc-4add-b6d1-01e41c561bfc" mVersion="1.0.0" mSequence="2" pVersion="0.0.1" xmlns="http://Citriz/Schemas">
    <People Action="U" Status="CD" PeopleID="2" PeopleShortName="Carl" PeopleLongName="Carl Thomas" PeopleTypeCode="Commercial" CountryCode="USA" PeopleStatus="Current">
            <PeopleRole Action="U" Status="CD" ID="2" CustomerRoleShortName="Carl" CustomerRoleLongName="Carl Thomas" TypeCode="INSS">
                    <SendRole RoleType="N" ActiveRole="Y"/>
            </PeopleRole>
    </People>
</Citriz>   
<Citriz ID="1d9a88fe-f9cc-4add-b6d1-01e41c561bfd" mVersion="1.0.0" mSequence="3" pVersion="0.0.1" xmlns="http://Citriz/Schemas">
    <People Action="U" Status="CD" PeopleID="3" PeopleShortName="Ryan" PeopleLongName="Ryan Black" PeopleTypeCode="Commercial" CountryCode="USA" PeopleStatus="Current">
            <PeopleRole Action="U" Status="CD" ID="3" CustomerRoleShortName="Ryan" CustomerRoleLongName="Ryan Black" TypeCode="INSS">
                    <SendRole RoleType="N" ActiveRole="Y"/>
            </PeopleRole>
    </People>
</Citriz>   

我需要所有那些子节点属性包含TypeCode="INSS"这个值的“Citriz”节点。或者如果有其他好的方法,请建议我。

【问题讨论】:

【参考方案1】:

鉴于您使用的是 LINQ to XML,我不会从 XPath 开始。我会使用:

XNamespace ns = "http://Citriz/Schemas";
var nodes = doc.Descendants(ns + "Citriz")
               .Where(x => x.Descendants()
                            .Any(y => (string) x.Attribute("TypeCode") == "INSS"));

或者如果它总是将是 PeopleCitriz 内的 PeopleRole 元素(每个级别只有一个元素):

XNamespace ns = "http://Citriz/Schemas";
var nodes = doc.Descendants(ns + "Citriz")
               .Where(x => (string) x.Element(ns + "People")
                                     .Element(ns + "PeopleRole")
                                     .Attribute("TypeCode") == "INSS"));

我确信这可以在 XPath 中明智地完成,但我个人认为 LINQ to XML 更简单,将数据部分(元素名称、预期值等)与“代码”部分(“我正在寻找后代”或“我正在寻找属性值”)。

【讨论】:

非常感谢您的回答。两种方式都不返回任何值。毫无疑问,我做错了什么或遗漏了什么。我需要额外的东西吗? @PankajMishra:此代码也因命名空间而失败 - 我没有发现命名空间。我已经适当地修复了代码。【参考方案2】:

我认为您对 Xml 命名空间有疑问

XNamespace ns = "http://Citriz/Schemas";
var peopleRole = XDocument.Parse(xml)
                    .Descendants(ns + "PeopleRole")
                    .Where(p => p.Attribute("TypeCode").Value == "INSS")
                    .ToList();

【讨论】:

非常感谢您的回答,但它没有返回两个节点。 @PankajMishra 我以为你想要第一个。只需将First 替换为Where。就这些。我更新了答案。【参考方案3】:

您可以认为 XPath 相当于在文件系统中导航目录树。向 xpath 查询添加额外的“目录”可以让您更深入地了解 DOM 树。

//PeopleRole[@TypeCode="inss"]/../..

将查找所有 PeopleRole 类型的节点,其 TypeCode 属性等于“inss”,然后向上移动到树中的级别,返回包含匹配的 PeopleRoles 的 &lt;Citriz&gt; 节点

【讨论】:

如果要在 XNode 中计算 XPath 表达式,可以使用 XPathSelectElements 扩展方法。见msdn.microsoft.com/en-us/library/bb387057.aspx

以上是关于如何为 XML 创建 XPath?的主要内容,如果未能解决你的问题,请参考以下文章

如何为最近的祖先提供 XPath?

Xpath—解决这个问题的良药

python爬虫入门

如何为 JPA 和 Hibernate 创建一个 persistence.xml 文件?

如何为相同类型的嵌套元素创建带有 key/keyrefs 的 xml 模式

如何为指定文件夹创建和保存包含完整文件和文件夹层次结构的 XML 文件?