忽略 XPath 中的名称空间,因为它可以是动态的

Ignore namespace in XPath as this can be dynamic

在过去的几个小时里,我在这里、博客和整个互联网上进行了广泛的研究。但是,到目前为止,我尝试过的任何事情都对我有用。 我所拥有的是一个使用以下命名空间生成的 xml 文件:

<DeploymentReport xmlns="http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02">

我无法控制这个文件的生成过程。据我了解,XPath 不使用名称空间是一个常见问题,除非它们已注册或删除。我不希望对 xml 文档进行任何修改,并且认为以某种方式让它忽略它可能会更好。

我已经尝试使用 /name()= 并且我已经尝试在我的 Xpath 查询中使用 local-name(其基本版本是):

//Operations/Operation/Item[@Type!='SqlIndex' and not(contains(@Value, 'Export'))]

但是,none 这些方法奏效了。可能是因为我使用的是 Powershell 版本 3,如果这很重要?

不想 注册命名空间的原因是因为它与本地安装的 Sql 版本相关(文件将生成那个版本)。这意味着它会导致任何其他版本出现问题。我不想注册一大堆,然后猜测它们将容纳哪些以适应将来出现的问题。

如果有人能提出处理这种情况的好方法,我将不胜感激?或者我别无希望,只能注册命名空间并在每个 Sql 版本中保持最新?

使用 local-name() 应该有效(为了便于阅读而包装):

//*[local-name()='Operations']
 /*[local-name()='Operation']
 /*[local-name()='Item'][@Type!='SqlIndex' and not(contains(@Value, 'Export'))]

XPath 不能与名称空间一起使用是不正确的。就是不太好用,仅此而已。

如果你能设法定义一个命名空间前缀,比如

xmlns:s="http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02"

那么很容易解决您的 Xml 元素。您的 XPath 表达式将是:

//s:Operations/s:Operation/s:Item[@Type!='SqlIndex' and not(contains(@Value, 'Export'))]

如果无法在您的上下文中声明命名空间前缀,那您就有麻烦了。

完整的表达式将是(为便于阅读而换行):

//*[local-name()='Operations'][namespace-uri()='http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02']
 /*[local-name()='Operation'][namespace-uri()='http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02']
 /*[local-name()='Item'][namespace-uri()='http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02']
   [@Type!='SqlIndex' and not(contains(@Value, 'Export'))]

当然,如果您省略 [namespace-uri()='http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02'],它仍然有效,但是如果您的 Xml 文档中有任何元素,那么您可能会不小心在不同的命名空间中寻址具有相同名称的元素.

在更高版本的 XPath 中,您也可以使用

//*:Operations/*:Operation/*:Item[@Type!='SqlIndex' and not(contains(@Value, 'Export'))]

忽略命名空间。