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

时间:2016-04-05 04:34:36

标签: xml xpath powershell-v3.0

我在这里过去几个小时,博客和互联网上进行了广泛的研究。但是,到目前为止,我没有尝试过任何事情。 我所拥有的是使用以下命名空间生成的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'))]

但是,这些方法都不起作用。或许,因为我使用Powershell版本3,如果这很重要吗?

不希望注册命名空间的原因是因为它绑定到本地安装的Sql版本(该文件将使用该版本生成)。这意味着它会导致任何其他版本的问题。我不想注册其中的很多内容,并猜测它们将来会适应哪些内容。

如果有人可以提出一个处理这种情况的好方法,我将不胜感激?或者我没有希望,但是要注册命名空间并使其与每个Sql版本保持同步?

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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'))]

忽略命名空间。