How can I break up a string with multiple XML root elements in PowerShell?

Question!

I am writing a PowerShell wrapper for an existing Perl script. The Perl script is fed a couple of parameters and goes off and configures all our HP iLO devices for us, and returns the results in an XML format. The problem is the result comes out as one big blob of multiple XML statements ie:

$strResult = & "perl locfg.pl -s $iloInterface -f $configXML"

<?xml version="1.0"?>
<RIBCL VERSION="2.22"/>
    <RESPONSE
    STATUS="0x0000"
    MESSAGE='No error'
     />
</RIBCL>

<?xml version="1.0"?>
<RIBCL VERSION="2.22"/>
<RESPONSE
    STATUS="0x0000"
    MESSAGE='No error'
     />
</RIBCL>

etc.

Attempting to then cast the $strResult to XML results in Error: "There are multiple root elements

Does anyone have any thoughts on how I can split up these XML statements in PowerShell to make them valid? I was thinking maybe a "dummy" root element may be in order? Or should I be looking at tweaking the underlying Perl script?

By : Ben Short


Answers

Either tweaking the Perl or wrapping a root element around it should work. You could also split the returned value on the empty lines then create an array of XML objects.

Actually I'm not sure that a root element would work since each of those bits have a version node in there.

By : EBGreen


I think it's easiest to split at the XML declaration <?xml .... First of all, you're getting the XML not as a single string, but as a String[], so we need join these:

[string]::Join("`n", $strresult)

ETA: The join operator was new in Powershell 2, I changed it using [string]::Join.

We can then split them up at the XML declaration:

-split "<\?xml"

Now we get multiple strings back, each of which is either empty (for the first one) or contains XML with a mutilated declaration. First let's strip out the empty ones:

| ? { $_.Trim() }

This will look whether the string is non-empty after removing all whitespace. Now we need to add the declaration back in we stripped:

| % { "<xml$_" }

And now we can also cast to XML:

| %{ [xml] $_ }

Note however, that your original XML was wrong to begin with. <RIBCL VERSION="2.22"/> is a self-closing root element and after the RESPONSE element you're closing the RIBCL element again. When I remove the / at the end of the opening RIBCL element all works fine:

PS Home:\> (gc t.txt) -join "`n" -split "<\?xml" |
>> ? { $_.Trim() } |
>> % { "<?xml$_" } |
>> % { [xml] $_ }
>>

xml                                                         RIBCL
---                                                         -----
version="1.0"                                               RIBCL
version="1.0"                                               RIBCL

ETA: If you can count on it, then it's certainly easier to split at the empty line, though:

[string]::Join("`n", $strResult) -split "`n`n"
By : Joey


This video can help you solving your question :)
By: admin