3

I'm trying to parse an XML which doesn't consist of uniform attributes. Example

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

The number of sub attributes is always the same but sometimes its a boolean and sometimes its a string and the tag name changes accordingly. The issue is not the type itself but, with Powershell, I have to know the tag name beforehand to obtain the value attached to it.

At the moment I'm doing something like this:

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

This works but I would like a more elegant solution + at the moment it's quite rigid and you have to cater for each and every possibility.

Is there a better way ?

Cheers

2 Answers 2

2

You can use ChildNodes property to access child elements by their order:

$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'
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

This doesn't necessarily solve the general problem of weird XML junk, but a helper function to coalesce the different possibilities could make things trimmer. Tested:

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

And you use it like value ($item.object) Boolean String, assuming all those nodes have the same valueXXX pattern. (If they're always from a fixed set, you can trim the usage down further by hard-coding that set in instead of $args. If there's a lot more variation than valueXXX, you'll need to tweak the helper function accordingly.)

Explanation: Uses $args to grab all the unnamed arguments, then loops through, building the property accessor on the fly from a string interpolation, and finds the first non-null result, which it then returns. Loop is labeled just to be sure.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.