使用Powershell解析不一致的XML对象

时间:2015-01-19 01:10:44

标签: xml parsing powershell

我试图解析一个不包含统一属性的XML。实施例

<root>
<object>
  <name>Object1</name>
  <valueString>string</valueString>
</object>
<object>
  <name>Object2</name>
  <valueBoolean>true</valueBoolean>
</object>
</root>

子属性的数量始终相同,但有时它是布尔值,有时是字符串,标签名称也会相应更改。问题不在于类型本身,但是对于Powershell,我必须事先知道标记名称以获取附加到它的值。

目前我正在做这样的事情:

foreach($item in $items){
  if(!$item.object.valueString){
     $temp = $item.object.valueBoolean
  }
  else{
     $temp = $item.object.valueString
  }
  $properties = @{
      Name = $item.object.Name
      value = $temp
  }
}

这有效,但我想要一个更优雅的解决方案+目前它很僵硬,你必须满足每一种可能性。

有更好的方法吗?

干杯

2 个答案:

答案 0 :(得分:2)

您可以使用ChildNodes属性按顺序访问子元素:

$xml=[xml]@'
<root>
  <object>
    <name>Object1</name>
    <valueString>string</valueString>
  </object>
  <object>
    <name>Object2</name>
    <valueBoolean>true</valueBoolean>
  </object>
</root>
'@
foreach($object in $xml.root.object){
    $value=$object.ChildNodes[1]
    [PSCustomObject]@{
        Name=$object.Name
        ValueName=$value.Name
        Value=$value.'#text'
    }
}

答案 1 :(得分:1)

这并不一定能解决奇怪的XML垃圾的一般问题,但是合并不同可能性的辅助函数可能会使事情变得微不足道。测试:

function value ($parent) {
    :args foreach ($name in $args) {
        $v = $parent.$("value$name")
        if ($v -ne $null) {$v; break args}
    }
}

假设所有节点都具有相同的valueXXX模式,您就像value ($item.object) Boolean String一样使用它。 (如果他们总是来自一个固定的设置,你可以通过硬编码而不是$args来进一步减少使用量。如果有更多的变化而不是valueXXX,你&#39 ; ll需要相应地调整辅助函数。)

说明:使用$args获取所有未命名的参数,然后循环,从字符串插值中动态构建属性访问器,并找到第一个非空结果,然后返回。循环被标记为确定。