使用 Powershell 解析 XML 以在被子节点屏蔽时获取 .Name 属性 的值
Parse XML with Powershell to get value of .Name property when masked by child node
在 Powershell 中,当 XML 元素有一个名为 'Name' 的子节点时,我如何获取其 .Name 属性 的值,该子节点掩盖了 属性.
# Assign XML that contains an element called 'Name' deliberately
# to mask the .Name property on the parent element.
$xml = [xml]@"
<People>
<Person>
<Name>Jo Bloggs</Name>
</Person>
</People>
"@
Write-Host $xml.People.FirstChild.Name
# > Jo Bloggs
#Expect to get the .Name property of the <Person> element but instead
# we get the 'Name' child node text.
# Use XML that doesn't mask the .Name property
$xml = [xml]@"
<People>
<Person>
<FullName>Jo Bloggs</FullName>
</Person>
</People>
"@
Write-Host $xml.People.FirstChild.Name
# > Person
# We now get what we originally expected, the value of the .Name
# property of the Person element itself.
当然,我可以调用 Person 元素的 .LocalName 属性 并得到预期的结果,但这不是通用解决方案,就好像 Person 元素有一个 LocalName 子元素一样,那也是蒙面
更新 2021-08-26:此后我发现了这个与我的问题非常相似的 SO 问题,并提供了一些详细的答案。
我认为在这种情况下没有办法告诉 PowerShell 优先考虑隐藏属性,但我很高兴被证明是错误的。
您可以遍历 XPathNavigator
并评估 XPath 字符串。这个
# or: [System.Xml.XPath.XPathDocument]::new("C:\Path\to\the\file.xml")
$doc = [System.Xml.XPath.XPathDocument]::new([System.IO.StringReader]::new(@"
<People>
<Person>
<Name>Jo Bloggs</Name>
</Person>
</People>
"@))
$xpath = $doc.CreateNavigator()
$xpath.Evaluate("name(/People/*[1])")
将打印 Person
.
根据这个问答
and
下面的行将获得内在的 .Name 属性 而不是装饰的 Powershell 属性.
$xml.People.FirstChild.get_Name()
更完整的解决方案演示为:
# Assign XML that contains an element called 'Name' deliberately
# to have Powershell decorate and thererfore Shadow the intrinsic
# .Name property on the parent element.
$xml = [xml]@"
<People>
<Person>
<Name>Jo Bloggs</Name>
</Person>
</People>
"@
# Solution to avoid issues with collision between decorated
# properties which shadow intrinsic element properties is to
# use the .get_<property-name>() method.
#
# In this case, .get_Name() should always return the intrinsic
# element property, and never the Powershell decorated property.
Write-Host $xml.People.FirstChild.get_Name()
# > Person
# This works
在 Powershell 中,当 XML 元素有一个名为 'Name' 的子节点时,我如何获取其 .Name 属性 的值,该子节点掩盖了 属性.
# Assign XML that contains an element called 'Name' deliberately
# to mask the .Name property on the parent element.
$xml = [xml]@"
<People>
<Person>
<Name>Jo Bloggs</Name>
</Person>
</People>
"@
Write-Host $xml.People.FirstChild.Name
# > Jo Bloggs
#Expect to get the .Name property of the <Person> element but instead
# we get the 'Name' child node text.
# Use XML that doesn't mask the .Name property
$xml = [xml]@"
<People>
<Person>
<FullName>Jo Bloggs</FullName>
</Person>
</People>
"@
Write-Host $xml.People.FirstChild.Name
# > Person
# We now get what we originally expected, the value of the .Name
# property of the Person element itself.
当然,我可以调用 Person 元素的 .LocalName 属性 并得到预期的结果,但这不是通用解决方案,就好像 Person 元素有一个 LocalName 子元素一样,那也是蒙面
更新 2021-08-26:此后我发现了这个与我的问题非常相似的 SO 问题,并提供了一些详细的答案。
我认为在这种情况下没有办法告诉 PowerShell 优先考虑隐藏属性,但我很高兴被证明是错误的。
您可以遍历 XPathNavigator
并评估 XPath 字符串。这个
# or: [System.Xml.XPath.XPathDocument]::new("C:\Path\to\the\file.xml")
$doc = [System.Xml.XPath.XPathDocument]::new([System.IO.StringReader]::new(@"
<People>
<Person>
<Name>Jo Bloggs</Name>
</Person>
</People>
"@))
$xpath = $doc.CreateNavigator()
$xpath.Evaluate("name(/People/*[1])")
将打印 Person
.
根据这个问答
下面的行将获得内在的 .Name 属性 而不是装饰的 Powershell 属性.
$xml.People.FirstChild.get_Name()
更完整的解决方案演示为:
# Assign XML that contains an element called 'Name' deliberately
# to have Powershell decorate and thererfore Shadow the intrinsic
# .Name property on the parent element.
$xml = [xml]@"
<People>
<Person>
<Name>Jo Bloggs</Name>
</Person>
</People>
"@
# Solution to avoid issues with collision between decorated
# properties which shadow intrinsic element properties is to
# use the .get_<property-name>() method.
#
# In this case, .get_Name() should always return the intrinsic
# element property, and never the Powershell decorated property.
Write-Host $xml.People.FirstChild.get_Name()
# > Person
# This works