2

is it possible to differentiate the origin of a value in XML data (attribute or element) once the data has been read? if I run the following script

$xml= [xml]@'
<?xml version="1.0" encoding="utf-8"?>
<root>
    <item id="001">
    </item>
    <item>
        <id>002</id>
    </item>
    <item id="003">
        <id>003 bis</id>
    </item>
</root>
'@

$items = Select-Xml -Xml $xml -XPath '//item'
$items | %{ $_.node }

I get the same structure in $_.node for id for the two first items and an array of values for id for the last one

id
--
001
002
{003, 003 bis}
Peyre
  • 397
  • 2
  • 14
  • Which one are you interested in? – Mathias R. Jessen Feb 15 '21 at 19:45
  • @MathiasR.Jessen one or the other. or both. I know I can modify the XPath filter to select only the attributes, or only the elements, but my question is: once loaded without any special filter, can I sort out the one coming from the attributes and the one coming from elements. – Peyre Feb 15 '21 at 21:35

1 Answers1

3

PowerShell's adaptation of the XML DOM represents both attributes and child elements as if they were properties of an XML element.

However, non-leaf XML elements (those that have attributes and/or child nodes that are elements) retain their System.Xml.XmlElement identity, and are simply decorated with the properties representing attributes and child elements, using PowerShell's ETS (Extended Type System).

Therefore, you also have access to an XmlElement's native type members (properties and methods), which allows you to distinguish between attributes and child elements:

$xml= [xml] @'
<?xml version="1.0" encoding="utf-8"?>
<root>
    <item id="001">
    </item>
    <item>
        <id>002</id>
    </item>
    <item id="003">
        <id>003 bis</id>
    </item>
</root>
'@

Select-Xml -Xml $xml -XPath '//item' | ForEach-Object {
  [pscustomobject] @{
    IdAttribute = $_.Node.GetAttribute('id')   # get attribute
    IdChildElement = $_.Node['id'].InnerText   # get child element 
  }
}

The above yields:

IdAttribute IdChildElement
----------- --------------
001         
            002
003         003 bis
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    I had to play a bit with it to make it work in strict mode but it's what I was looking for – Peyre Feb 24 '21 at 21:23