【发布时间】:2017-03-14 14:44:25
【问题描述】:
匹配属性和元素的正确 XPath 语法是什么?
更多信息
我创建了以下函数来查找包含给定值的元素和属性:
function Get-XPathToValue {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[xml]$Xml
,
[Parameter(Mandatory)]
[string]$Value
)
process {
$Xml.SelectNodes("//*[.='{0}']" -f ($Value -replace "'","''")) | %{
$xpath = ''
$elem = $_
while (($elem -ne $null) -and ($elem.NodeType -ne 'Document')) {
$xpath = '/' + $elem.Name + $xpath
$elem = $elem.SelectSingleNode('..')
}
$xpath
}
}
}
这匹配元素,但不匹配属性。
通过将$Xml.SelectNodes("//*[.='{0}']" 替换为$Xml.SelectNodes("//@*[.='{0}']",我可以匹配属性,但不能匹配元素。
示例
[xml]$sampleXml = @"
<root>
<child1>
<child2 attribute1='hello'>
<ignoreMe>what</ignoreMe>
<child3>hello</child3>
<ignoreMe2>world</ignoreMe2>
</child2>
<child2Part2 attribute2="ignored">hello</child2Part2>
</child1>
<notMe>
<norMe>Not here</norMe>
</notMe>
</root>
"@
Get-XPathToValue -Xml $sampleXml -Value 'hello'
返回:
/root/child1/child2/child3
/root/child1/child2Part2
应该返回:
/root/child1/child2/attribute1
/root/child1/child2/child3
/root/child1/child2Part2
你尝试过什么?
我尝试匹配:
-
//@*|*[.='{0}']- 返回匹配元素,但返回所有属性。 -
//*|@*[.='{0}']- 返回匹配的属性,但返回所有元素。 -
//*[.='{0}']|@*[.='{0}']"- 返回匹配的元素。 -
//@*[.='{0}']|*[.='{0}']"- 返回匹配的属性。 -
//(@*|*)[.='{0}']"- 抛出异常。
【问题讨论】:
-
您生成 XPath 字符串的算法有缺陷。只要在同一级别中存在多个同名元素,它就会崩溃。无论如何,如果我可以问的话,它有什么意义?`
-
好点;我会细化的。这只是一个帮助我进行分析的实用程序。我有时必须处理大型 XML 文件,我必须在文本编辑器中打开它们,找到被报告为错误的值,然后计算出相关元素的 xpath,以便我可以编写一个脚本来比较这个值在许多其他文件中使用相同的值,看看它们是否也有问题。如果我能帮上忙,我不喜欢手动做事;所以这只是节省了一点努力。它不是任何面向用户的解决方案的代码;只是我的实用腰带的东西。
-
那里还有一个缺陷。 XPath 没有字符串转义。你不能用
''替换',一切都很好,这不是它的工作原理。 -
第三个缺陷是它完全忽略了 XML 命名空间。
标签: xml powershell xpath attributes element