Search code examples
xmlpowershellxpathgpo

Powershell Select-XML - Trouble with XPath as absolute Path


Hello powershell fellows,

i have another issue with powershell and xml.

What i try to do: I have an XML File (more accurately, it is a xml export of a AD GPO). This XML looks very similar to this:

<?xml version="1.0" encoding="UTF-16"?>
-<GPO xmlns="http://www.microsoft.com/GroupPolicy/Settings" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    -<Identifier>
        <Identifier xmlns="http://www.microsoft.com/GroupPolicy/Types"></Identifier>
        <Domain xmlns="http://www.microsoft.com/GroupPolicy/Types">Testdomain.local</Domain>
    </Identifier>
    <Name>ExampleName</Name>
    <IncludeComments>true</IncludeComments>
    <CreatedTime>2022-07-26T11:12:25</CreatedTime>
    <ModifiedTime>2022-07-26T11:56:44</ModifiedTime>
    <ReadTime>2022-07-26T11:56:52.7975554Z</ReadTime>
    -<Computer>
        <VersionDirectory>1</VersionDirectory>
        <VersionSysvol>1</VersionSysvol>
        <Enabled>true</Enabled>
        -<ExtensionData>
            -<Extension xsi:type="q1:SecuritySettings" xmlns:q1="http://www.microsoft.com/GroupPolicy/Settings/Security">
                -<q1:SecurityOptions>
                    <q1:KeyName>TestKeyName</q1:KeyName>
                    <q1:SettingNumber>5</q1:SettingNumber>
                    -<q1:Display>
                        <q1:Name>TestName</q1:Name>
                        <q1:Units/>
                        <q1:DisplayString>TestValue</q1:DisplayString>
                    </q1:Display>
                </q1:SecurityOptions>
         ...

Now i want to address these xml nodes with Select-XML cmdlet. I need to use a absolute Xpath Path. Lets say i want to get the value of "SecurityOptions/Display/Name".

I tried something like this:

$namespace = @{ns="http://www.microsoft.com/GroupPolicy/Settings";xsi="http://www.w3.org/2001/XMLSchema-instance";xsd="http://www.w3.org/2001/XMLSchema";q1="http://www.microsoft.com/GroupPolicy/Settings/Security"}

$xpath = '/q1:SecurityOptions/q1:Display/q1:Name'
$result = (Select-Xml -Path "C:\examplepath\example.xml" -XPath $xpath -Namespace $namespace).Node.InnerText

But this gets me no value at all :/

What works:

On the other hand, when i do not use an absolute path like:

$xpath = '//q1:Name'
$result = (Select-Xml -Path "C:\examplepath\example.xml" -XPath $xpath -Namespace $namespace).Node.InnerText

It gives me some result. But i want to address the XML Nodes with an absolute path not only with a relative path.

Maybe anyone can tell me what i am doing wrong here. :)

Thank you in advance !


Solution

  • The answer is as simple as adding a missing /. Not sure why you have to use an absolute path, but in your relative path, your expression //q1:Name starts with // which covers all descendants nodes of the root with that name. In your absolute path expression /q1:SecurityOptions... you start with /, which looks only for direct child elements of the root by that name. But the /q1:SecurityOptionselement is burred several layers down the tree.

    So long story short, changing your xpath expression to

    '//q1:SecurityOptions/q1:Display/q1:Name'
    

    should work.