0

I am struggling with Powershell, XML and XPath.

I want a script that will read a file, extract the node I need and convert to an object I can use in the script.

The file looks like:

<?xml version="1.0"?>
<Objs xmlns="http://schemas.microsoft.com/powershell/2004/04" Version="1.1.0.1">
    <Obj RefId="0">
        <TN RefId="0">
            <T>System.Object</T>
        </TN>
        <Props>
            <Obj N="Set1" RefId="1">
                <TN RefId="1">
                    <T>System.Object</T>
                </TN>
                <Props>
                    <S N="Folder">C:\t1</S>
                    <Obj N="Configs" RefId="10">
                        <TN RefId="10">
                            <T>System.Object</T>
                        </TN>
                        <Props>
                            <S N="N1">Geralt</S>
                            <S N="N2">Ciri</S>
                        </Props>
                    </Obj>
                </Props>
            </Obj>
            <Obj N="Set2" RefId="2">
                <TN RefId="2">
                    <T>System.Object</T>
                </TN>
                <Props>
                    <S N="Folder">C:\t2</S>
                    <Obj N="Configs" RefId="20">
                        <TN RefId="20">
                            <T>System.Object</T>
                        </TN>
                        <Props>
                            <S N="N1">Triss</S>
                            <S N="N2">Yen</S>
                        </Props>
                    </Obj>
                </Props>
            </Obj>
        </Props>
    </Obj>
</Objs>

I wrote this code:

$path = "c:\file.xml"
$xpath = "/ns:Objs/ns:Obj/ns:Props/ns:Obj[@N='Set2']"
$ns = "@{ns='http://schemas.microsoft.com/powershell/2004/04'}"

[xml]$apps = Select-Xml -Path $path -XPath $xpath -Namespace $ns

I was expecting to be able to write :

Write-Host "Folder is: $apps.Folder" -> C:\t1 Write-Host "Config is: $apps.Configs.N2" -> Yen

But I can't get an object because of this error:

Cannot convert value "...". Error: "This document already has a 'DocumentElement' node."
At line:1 char:1
+ [xml]$t = Select-Xml -Path $path -XPath "/ns:Objs/ns:Obj/ns:Props/ns:Obj[@N='Set2']"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

Any suggestions ?

1 Answer 1

1

This looks like an output from Export-CliXml. It would be easier to deserialize using Import-CliXml:

$apps = Import-Clixml -Path c:\file.xml
$apps.Set2.Folder
$apps.Set2.Configs.N2

In your original code, the namespace has the wrong syntax. It should be a hash table.

$ns = @{ns='http://schemas.microsoft.com/powershell/2004/04'}

Surrounding the hash table code in double quotes creates a string instead. If we use your XPATH expression for the Obj node that contains Set2, you will need to further drill down the node tree.

$path = "c:\file.xml"
$xpath = "/ns:Objs/ns:Obj/ns:Props/ns:Obj[@N='Set2']"
$ns = @{ns='http://schemas.microsoft.com/powershell/2004/04'}

$apps = Select-Xml -Path $path -XPath $xpath -Namespace $ns
$apps.Node.Props.S.Innertext # Folder value
$apps.Node.Props.Obj.Props.S.Innertext # Configs values
Sign up to request clarification or add additional context in comments.

1 Comment

I needed to use the XPath as the value 'Set2' that I searched in my sample will be a variable inside an Azure Pipeline and I also need to select N1 or N2 based on a variable... Either I stay with XPath and I'm guessing I would need a different XPath each time I need to find a data based on variable. Doesn't seem very easy to read so I'll try with Import-Clixml and loops. Thanks again, I learned new stuff !!

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.