PowerShell – Not all XML properties are passed to the pipeline

I am writing a fairly substantial Posh module as a CLI front end for a set of RESTful web services. I have a strange problem that I was able to characterize, but did not find a clean solution.

I don’t always know what attribute is expected, and some nodes may have a certain attribute, and other nodes may not have that attribute. My question is sometimes (often read) if an attribute does not exist in Of all nodes, it will not be passed to any node’s pipeline. It seems to be related to the attributes in the first node in the XML.

For a very simple example, please consider this is the XML file example .xml content:



Joe
Grand Poobah
1234


Fred
1234

I imported it and assigned it to the xml casting variable:

[xml]$stuff = Get-Content .\example.xml

Then I pipe it to the format table (or out-gridview, export-csv, etc.)

$stuff.members.member | ft -AutoSize

name rank serialnumber
---- ---- --------- ---
Joe Grand Poobah 1234
Fred 1234

It works well.

Now, if the FIRST node has no rank attribute:



Fred
1234


Joe< /name>
Grand Poobah
1234

Now, when I perform the same import and pass it to the pipeline, the “rank” attribute is not passed to the pipeline.

$stuff.members.member | ft- AutoSize

name serialnumber
---- ------------
Fred 1234
Joe 1234

I can force it by explicitly naming properties:

$stuff.members.member | select-object -Property name, rank, serialnumber | ft

name rank serialnumber
---- ---- ------------
Fred 1234
Joe Grand Poobah 1234

Explicitly naming properties is a wrong recipe, because properties can be added without warning. If possible, I want to keep the code flexible to handle new properties.

I thought I could use “select-object- property *”, but I added a lot of XML things inserted by powershell that I don’t want, and there is still no pipeline rank attribute.

$stuff.members.member | select-object- Property *| ft -AutoSize
name serialnumber Loc alName NamespaceURI Prefix NodeType ParentNode OwnerDocument IsEmpty Attributes
---- ------------ --------- ------------- ----- -------- ---------- ------------- ------- ------- ---
Fred 1234 member Element members #document False {}
Joe 1234 member Element members #document False {}

Is anyone familiar with a good way to handle this situation? I did not find any good clues on Google search.

The XML element must be “passed to the pipeline “. What you are looking at is a feature of format-table: it only looks at the first object in the list to determine the column to be printed.

This is mainly for performance reasons. Otherwise , format-table must iterate the list twice-once to determine which attributes are output, the second time to actually output them. In addition, the items in the list are usually uniform.

In all other cases, the rules are “clear Better than implicit” applies:

$stuff.members.member | ft name, rank, serialnumber -AutoSize

< p>I am writing a fairly substantial Posh module as a CLI front end for a set of RESTful web services. I have a strange problem that I was able to characterize, but did not find a clean solution.

I don’t always know what attribute to expect, and some nodes may have a certain attribute, and other nodes may not have that attribute. My question is sometimes (often read) if an attribute does not exist in all nodes, it will not be passed The pipeline to any node. It seems to be related to the attributes in the first node in the XML.

For a very simple example, consider this is the content of the XML file example.xml:



Joe
Grand Poobah
< serialnumber>1234


Fred
1234

I imported it and assigned it to the xml casting variable:

[xml]$stuff = Get-Content .\example .xml

Then I pipe it to the format table (or out-gridview, export-csv, etc.)

$stuff.members.member | ft -AutoSize

name rank serialnumber
---- ---- ------------
Joe Grand Poobah 1234
Fred 1234

It works well.

Now, if the FIRST node has no rank attribute:


< member>
Fred
1234


Joe< /name>
Grand Poobah
1234

Now, when I perform the same import and pass it to the pipeline, the “rank” attribute is not passed to the pipeline.

$stuff.members.member | ft- AutoSize

name serialnumber
---- ------------
Fred 1234
Joe 1234

I can force it by explicitly naming properties:

$stuff.members.member | select-object -Property name, rank, serialnumber | ft

name rank serialnumber
---- ---- ------------Fred 1234
Joe Grand Poobah 1234

Explicitly naming attributes is a wrong recipe, because attributes can be added without warning. If possible, I want to keep the code flexible New attributes.

I thought I could use “select-object -property *”, but I added a lot of XML stuff that I don’t want in powershell insertion, and there is still no pipeline rank attribute.

< p>

$stuff.members.member | select-object -Property *| ft -AutoSize
name serialnumber LocalName NamespaceURI Prefix NodeType ParentNode OwnerDocument IsEmpty Attributes
---- - ---------- --------- ------------ ------ -------- ----- ----- ------------- ------- ----------
Fred 1234 member Element members #document False {}< br />Joe 1234 member Element members #document False {}

Is anyone familiar with a good way to handle this situation? I did not find any good clues on Google search.

The XML element must be “passed to the pipeline”. What you are looking at is a format-table Features: It only looks at the first object in the list to determine the column to be printed.

This is mainly for performance reasons. Otherwise, format-table must iterate the list twice-once to determine Which attributes are output and actually output them the second time. Also, the items in the list are usually uniform.

In all other cases, the rule “explicit is better than implicit” applies:

$stuff.members.member | ft name, rank, serialnumber -AutoSize

Leave a Comment

Your email address will not be published.