2016-10-03 27 views
0

要在PowerShell中获取XML元素的值,我们可以通过将元素视为PowerShell对象的属性来简单地写出路径;即$xml.RootElement.ChildElement.GrandChild。然而,如果我们感兴趣的元素有一个关联的属性,为了获得文本值,我们需要向下钻取到文本节点;然后,即$xml.RootElement.ChildElement.GrandChild.'#text'在使用PowerShell从XML中获取XML文本值时智能处理属性

不幸的是,当元素没有属性时,我们不能使用文本节点;即在该情景中,$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 
+0

PS。我注意到在我的命令中加入'$ xmlElement.GetType()'表明元素的类型根据是否存在任何属性而改变;即如果它是'XmlElement',如果没有,则是'String' .. – JohnLBevan

回答

1

SelectNodes功能解决了这个问题:

$example.SelectNodes('/demo/element').'#text' 

$example.SelectNodes('/demo/element/text()').Value 

工作为EXPE反恐执行局。

它也可以以这种方式更新节点:

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>