【问题标题】:Powershell: XPath cannot select when element has "xmlns" tag?Powershell:当元素具有“xmlns”标签时,XPath 无法选择?
【发布时间】:2015-09-10 11:32:33
【问题描述】:

我有一个非常简单的xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<First>
  <Second>
    <Folder>today</Folder>
    <FileCount>10</FileCount>
  </Second>
  <Second>
    <Folder>tomorrow</Folder>
    <FileCount>90</FileCount>
  </Second>
  <Second>
    <Folder>yesterday</Folder>
    <FileCount>22</FileCount>
  </Second>
</First>

然后我有一个 powershell 脚本来选择“文件夹”元素:

[xml]$xml=Get-Content "D:\m.xml"
$xml.SelectNodes("//Folder")

它输出:

#text                                                                                                                                                                            
-----                                                                                                                                                                            
today                                                                                                                                                                            
tomorrow                                                                                                                                                                         
yesterday 

没问题。但是,如果我更改 xml 文件以将“xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 添加到“First”,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<First xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Second>
    <Folder>today</Folder>
    <FileCount>10</FileCount>
  </Second>
  <Second>
    <Folder>tomorrow</Folder>
    <FileCount>90</FileCount>
  </Second>
  <Second>
    <Folder>yesterday</Folder>
    <FileCount>22</FileCount>
  </Second>
</First>

然后,我的 powershell 脚本什么也不输出。 为什么?如何更改我的 powershell 脚本以支持此 xmlns?

非常感谢。

【问题讨论】:

    标签: powershell xpath xml-namespaces default-namespace


    【解决方案1】:

    您添加的是默认命名空间。与前缀命名空间不同,后代元素隐式继承祖先默认命名空间,除非另有说明(使用显式前缀或指向不同 URI 的本地默认命名空间)。

    要选择命名空间中的元素,您需要定义指向命名空间 URI 的前缀并在 XPath 中正确使用该前缀,例如:

    $ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
    $ns.AddNamespace("d", $xml.DocumentElement.NamespaceURI)
    $xml.SelectNodes("//d:Folder", $ns)
    

    【讨论】:

    • 谢谢,但是 seesm (1) 创建 ns 添加 "d" (2) 使用 "d"-----对我来说有点多余。为什么在确保 $ns 包含“d”的同时还要费心选择//d:Folder?我觉得这里没有必要。另外,默认命名空间的名称是随机选择的,我看不出它存在的价值。许多有一些更复杂的场景需要这来区分?你能举个例子吗?
    • 确实前缀d是随机选择的,重要的是它指向的URI,以及$ns所携带的信息。也就是说,您需要步骤 (1) 和 (2)
    • 为了避免混淆,它不是随机选择的 default namespace,而是随机选择的 XPath 中使用的 前缀 .前缀可以是任何东西,粗略地说,只要它指向默认命名空间 URI
    • 谢谢,但是我可以想到如果我是XML标准的实现者,我会认为默认命名空间为“”,那么使用空前缀就可以了。当然我的假设是不正确的,但为什么不能这样呢?我的意思是,是否有任何复杂的情况需要我们总是需要一个随机选择的字符串来表示默认命名空间,否则我们会产生逻辑冲突?
    • XML 解析器跨语言的这种行为 - 可能不是全部,但我知道其中很多 - 是由于 XPath 规范 - 我在某处读过这个,可能是错误的;欢迎指正-。在 XPath 中,所有没有前缀的元素都绑定到空命名空间,而在 XML 中,没有命名空间的元素可以在默认命名空间中。无论如何,我恐怕不知道为什么 XPath 会这样设计
    猜你喜欢
    • 1970-01-01
    • 2017-10-07
    • 2018-08-05
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多