使用 PowerShell 从 XML 获取 xml 文本值时智能处理属性
Intelligently handling attributes when fetching an xml text value from XML using PowerShell
要在 powershell 中获取 XML 元素的值,我们可以通过将元素视为 PowerShell 对象的属性来简单地写出路径;即 $xml.RootElement.ChildElement.GrandChild
.
但是,如果我们感兴趣的元素具有关联的属性,则要获取文本值,我们需要向下钻取到文本节点;即 $xml.RootElement.ChildElement.GrandChild.'#text'
.
遗憾的是当元素没有属性时,我们不能使用文本节点;即在那种情况下,$xml.RootElement.ChildElement.GrandChild.'#text'
不起作用。
Clear-Host
$example = [xml](@"
<demo>
<element attribute='1'>10</element>
<element>20</element>
</demo>
"@)
"just the element"
$example.demo.element
"element's text"
$example.demo.element.'#text'
我为此编写了一个糟糕的解决方法,但怀疑这是错误的方法/PowerShell 有更优雅的方法来解决这个问题。
我讨厌的解决方法:
function Get-TextNode {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)]
$xmlElement
)
process {
if($xmlElement.Attributes.Count -eq 0) {
$xmlElement
} else {
$xmlElement.'#text'
}
}
}
$example.demo.element | Get-TextNode
SelectNodes
函数解决了这个问题:
即
$example.SelectNodes('/demo/element').'#text'
或
$example.SelectNodes('/demo/element/text()').Value
按预期工作。
也可以通过这种方式更新节点:
Clear-Host
$example = [xml](@"
<demo>
<x>5</x>
<element attribute='1'>10</element>
<element>20</element>
</demo>
"@)
$example.OuterXml
#Result: <demo><x>5</x><element attribute="1">10</element><element>20</element></demo>
$example.SelectNodes('/demo/element/text()') | %{
$_.value = $_.ParentNode.ParentNode.SelectSingleNode('./x/text()').Value
}
$example.OuterXml
#Result: <demo><x>5</x><element attribute="1">5</element><element>5</element></demo>
要在 powershell 中获取 XML 元素的值,我们可以通过将元素视为 PowerShell 对象的属性来简单地写出路径;即 $xml.RootElement.ChildElement.GrandChild
.
但是,如果我们感兴趣的元素具有关联的属性,则要获取文本值,我们需要向下钻取到文本节点;即 $xml.RootElement.ChildElement.GrandChild.'#text'
.
遗憾的是当元素没有属性时,我们不能使用文本节点;即在那种情况下,$xml.RootElement.ChildElement.GrandChild.'#text'
不起作用。
Clear-Host
$example = [xml](@"
<demo>
<element attribute='1'>10</element>
<element>20</element>
</demo>
"@)
"just the element"
$example.demo.element
"element's text"
$example.demo.element.'#text'
我为此编写了一个糟糕的解决方法,但怀疑这是错误的方法/PowerShell 有更优雅的方法来解决这个问题。
我讨厌的解决方法:
function Get-TextNode {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)]
$xmlElement
)
process {
if($xmlElement.Attributes.Count -eq 0) {
$xmlElement
} else {
$xmlElement.'#text'
}
}
}
$example.demo.element | Get-TextNode
SelectNodes
函数解决了这个问题:
即
$example.SelectNodes('/demo/element').'#text'
或
$example.SelectNodes('/demo/element/text()').Value
按预期工作。
也可以通过这种方式更新节点:
Clear-Host
$example = [xml](@"
<demo>
<x>5</x>
<element attribute='1'>10</element>
<element>20</element>
</demo>
"@)
$example.OuterXml
#Result: <demo><x>5</x><element attribute="1">10</element><element>20</element></demo>
$example.SelectNodes('/demo/element/text()') | %{
$_.value = $_.ParentNode.ParentNode.SelectSingleNode('./x/text()').Value
}
$example.OuterXml
#Result: <demo><x>5</x><element attribute="1">5</element><element>5</element></demo>