【问题标题】:ASP.NET Select XML nodes based on attribute value in child elementASP.NET 根据子元素中的属性值选择 XML 节点
【发布时间】:2017-11-03 20:06:09
【问题描述】:

我正在尝试遍历下面的 XML 并找到所有 entry 元素,其中底层 category 元素的值 collection 用于 thr term 属性。以下示例中有 2 个。然后对于那些获取 link 元素上的 href 属性的值。 但是,我似乎找不到合适的选择器:

<feed xmlns="http://www.w3.org/2005/Atom">
    <title>demo</title>
    <id>urn:uuid:071d9650-ae6c-11e7-8f1a-0800200c9a66</id>
    <link rel="self" href="https://test.com/atom/index.xml"/>
    <updated>2017-10-11T14:37:33+02:00</updated>
    <author>
        <name>Test</name>
        <uri>http://www.test.com</uri>
    </author>
    <generator version="1.8">Agent</generator>
    <entry>
        <title>YDEMO</title>
        <id>urn:uuid:15f44340-ae6c-11e7-8f1a-0800200c9a66</id>
        <category term="collection"/>
        <published>2017-10-11T13:41:53+02:00</published>
        <updated>2017-10-11T14:37:33+02:00</updated>
        <link rel="alternate" href="https://www.myurl.com" type="text/xml"/>
        <mcp:projectScenario xmlns:mcp="http://webservice.yes-co.nl/3mcp/1.5/atom-extension">NBvh</mcp:projectScenario>
    </entry>
    <entry>
        <title>DEMO 2</title>
        <id>urn:uuid:25f44340-ae6c-11e7-8f1a-0800200c9a00</id>
        <category term="collection"/>
        <published>2017-10-11T13:42:53+02:00</published>
        <updated>2017-10-11T14:38:33+02:00</updated>
        <link rel="alternate" href="https://www.myurl2.com" type="text/xml"/>
        <mcp:projectScenario xmlns:mcp="http://webservice.yes-co.nl/3mcp/1.5/atom-extension">BBvh</mcp:projectScenario>
    </entry>
    <entry>
        <title>photo</title>
        <id>12</id>
        <category term="metadata"/>
        <updated>2016-10-11T14:38:33+02:00</updated>
        <link rel="alternate" href="https://www.myurl2.com" type="text/xml"/>
    </entry>
    <entry
        xmlns:mcp="http://webservice.yes-co.nl/3mcp/1.5/atom-extension">
        <title>No title</title>
        <id>urn:uuid:6d65c57f-621f-4c15-8a1d-5dc967423d5d</id>
        <category term="media"/>
        <published>2017-10-11T13:39:43+02:00</published>
        <updated>2017-10-11T13:39:43+02:00</updated>
        <link
            xmlns:mcp="http://webservice.yes-co.nl/3mcp/1.5/atom-extension" rel="related" href="https://webservice.yes-co.com/3mcp/1.5/15f44340-ae6c-11e7-8f1a-0800200c9a66/media/6d65c57f-621f-4c15-8a1d-5dc967423d5d-large.jpg" type="image/jpg" mcp:mediaFormat="large"/>
    </entry>        
</feed>

到目前为止,这是我的代码,但即使 data 变量包含上述 XML,nodeList.Count 行返回 0 个结果:

    Dim WC As New WebClient
    Dim data As String = WC.DownloadString("http://localhost/index.xml")

    Dim indexXML As New XmlDocument
    indexXML.LoadXml(data)

    Dim mgr As XmlNamespaceManager = New XmlNamespaceManager(indexXML.NameTable)
    mgr.AddNamespace("http://www.w3.org/2005/Atom", indexXML.DocumentElement.NamespaceURI)

    Dim node As XmlNode

    Dim root As XmlNode = indexXML.DocumentElement
    Dim nodeList As XmlNodeList = root.SelectNodes("/feed/entry")

    'now loop through all elements  with "category term=collection" in index.xml
    For i As Integer = 0 To nodeList.Count - 1
        If nodeList(i).SelectSingleNode("/category/@term=collection") IsNot Nothing Then
            LogMessage(nodeList(i).SelectSingleNode("/category/link/@href").Value)
        End If
    Next i  

更新 1
我想选择具有term=collection 的类别节点的所有“条目”元素。该部分通过以下语句起作用:indexXML.SelectNodes("/atom:feed/atom:entry[atom:category/@term=""collection""]", mgr)

我想从入口节点开始,然后我想选择入口的子元素链接的href属性(以及将来entry的其他子元素。 但是,我在下面尝试的所有示例都没有返回 href 属性的值。我该如何解决?

我现在有了这个:

Dim mgr As XmlNamespaceManager = New XmlNamespaceManager(indexXML.NameTable)
mgr.AddNamespace("atom", "http://www.w3.org/2005/Atom")

Dim root As XmlNode = indexXML.DocumentElement
Dim nodeList As XmlNodeList = indexXML.SelectNodes("/atom:feed/atom:entry[atom:category/@term=""collection""]", mgr)

'now loop through all collections in index.xml

For i As Integer = 0 To nodeList.Count - 1 '1 result found

'NONE OF CALLS BELOW RETURN THE VALUE OF HREF ATTRIBUTE
    If nodeList(i).SelectSingleNode("atom:/link/@href", mgr) IsNot Nothing Then
        LogMessage(nodeList(i).SelectSingleNode("atom:/link/@href", mgr).Value)
'error: 'atom:/link/@href' has an invalid qualified name.
    End If
Next i

更新 2 感谢@Pawel,我能够选择所有具有projectentry 节点作为category 节点上term 属性的值,如下所示:

objectsXML.SelectNodes("/atom:feed/atom:entry[atom:category/@term=""project""]", mgr)

但是,我如何向此选择器添加额外的标准以过滤出具有 NBvhBBvh 值的 entry 节点 mcp:projectScenario

更新 3 我为管理器添加了一个额外的命名空间:

mgr.AddNamespace("atom", "http://www.w3.org/2005/Atom")
mgr.AddNamespace("mcp", "http://webservice.yes-co.nl/3mcp/1.5/atom-extension")

但是当我尝试通过 uuid 选择媒体元素的href 属性时,我得到错误:Object reference not set to an instance of an object.

我的代码:

objectsXML.SelectSingleNode("/atom:feed/atom:entry[atom:id=""urn:uuid:" + "6d65c57f-621f-4c15-8a1d-5dc967423d5d" + """]/mcp:link/@href", mgr).InnerText

【问题讨论】:

  • 不知道asp 中的代码应该是什么样子,但/feed/entry[category/@term="collection"]/link/@href 应该会返回所需节点的列表
  • 嗨,不幸的是,该选择器仍然有 0 个结果。顺便说一句:我想选择entry 节点的原因是我可以轻松选择其他子节点(如link,但还有更多)

标签: asp.net xml xpath selectnodes


【解决方案1】:

文档使用http://www.w3.org/2005/Atom 命名空间。您需要将此命名空间绑定到 uri 前缀并在 XPath 中使用此前缀。 如果您将命名空间绑定到 atom 前缀,如下所示:

var nsmanager = new XmlNamespaceManager(indexXML.NameTable);
nsmanager.AddNamespace("atom", "http://www.w3.org/2005/Atom");

如果您传递命名空间管理器,您将能够在 XPath 表达式中使用此前缀,例如:

indexXML.SelectNodes("/atom:feed/atom:entry[atom:category/@term="collection"]/atom:link/@href", nsmanager)

【讨论】:

  • 谢谢。有没有一种方法可以让我不必将 atom 前缀添加到我的所有 XSL 表达式并传递命名空间管理器?老实说,我认为这让事情变得过于复杂。我可以想象最初设置它,但之后我想使用常规的非前缀 XSL 表达式......这可能吗?我尝试了 mgr.AddNamespace("", "http://www.w3.org/2005/Atom") 然后 Dim nodeList As XmlNodeList = root.SelectNodes("/feed/entry") 但仍然返回 0 个结果。
  • 有一些选择,但我不确定它们是否更好。您可以使用本地名称,例如/*[local-name() = 'feed']。您可以遍历树手动检查 LocalNode 属性。您可以使用 Linq to Xml 直接使用命名空间 Uri。您不能使用空字符串作为命名空间前缀。顺便提一句。在您在代码中查找 category 的地方,您使用的是绝对节点路径(即从 / 开始,但它应该相对于当前节点)
  • 因为不是atom:/link而是atom:link
  • @Flo 您需要将mcp 前缀添加到命名空间管理器,就像您使用atom 前缀一样。
  • @Flo 更新 3 中的路径应该有 atom:link,而不是 mcp:link。您收到错误消息,因为路径无法选择任何内容并且 SelectSingleNode 正在返回 Nothing
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
相关资源
最近更新 更多