Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConvertTo-Xml fails with nested custom objects: omits closing </Objects> tag #8308

Closed
mklement0 opened this issue Nov 18, 2018 · 10 comments · Fixed by #8476
Closed

ConvertTo-Xml fails with nested custom objects: omits closing </Objects> tag #8308

mklement0 opened this issue Nov 18, 2018 · 10 comments · Fixed by #8476
Labels
Issue-Bug Issue has been identified as a bug in the product Resolution-Fixed The issue is fixed. Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors WG-Cmdlets-Utility cmdlets in the Microsoft.PowerShell.Utility module

Comments

@mklement0
Copy link
Contributor

See repro below.

As an aside (that will probably become a docs issue): What is the purpose of ConvertTo-Xml? The docs suggest that it is the in-memory counterpart to Export-Clixml, however:

  • It produces different XML representations,
  • which, if saved to a file, cannot be re-imported with Import-Clixml

Steps to reproduce

[pscustomobject] @{ a = [pscustomobject] @{ aa=11; bb=22 } } | ConvertTo-Xml

Expected behavior

Should output an [xml] instance that is the serialization of the custom object.

Actual behavior

The following error occurs:

ConvertTo-Xml : Unexpected end of file has occurred. The following elements are not closed: Objects.
  • If you use -As String, you don't get an error, but the XML string output too is missing the closing </Objects> tag.

  • Removing the 2nd property (bb) from the nested custom object makes the problem go away.

  • Using [hashtable] instances instead of [pscustomobject]s makes the problem go away.

  • Export-Clixml does not exhibit the problem.

Environment data

PowerShell Core 6.2.0-preview.1 on macOS 10.14.1
PowerShell Core 6.2.0-preview.1 on Ubuntu 16.04.5 LTS
PowerShell Core 6.2.0-preview.1 on Microsoft Windows 10 Pro (64-bit; Version 1803, OS Build: 17134.345)
Windows PowerShell v5.1.17134.228 on Microsoft Windows 10 Pro (64-bit; Version 1803, OS Build: 17134.345)
@mklement0 mklement0 changed the title ConvertTo-Xml fails with nested custom objects: omits closing </Objects> ConvertTo-Xml fails with nested custom objects: omits closing </Objects> tag Nov 18, 2018
@SteveL-MSFT SteveL-MSFT added WG-Cmdlets-Utility cmdlets in the Microsoft.PowerShell.Utility module Issue-Bug Issue has been identified as a bug in the product labels Nov 18, 2018
@SteveL-MSFT
Copy link
Member

Fails with Windows PowerShell 5.1 so not a regression. Seems specific to nested [PSCustomObject]. Other cases work

get-process | select -first 1 | convertto-xml

@SteveL-MSFT SteveL-MSFT added the Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors label Nov 18, 2018
@mklement0
Copy link
Contributor Author

mklement0 commented Nov 18, 2018

Thanks, @SteveL-MSFT. Generally, I only include a Windows PowerShell version in the Environment data section if it isn't a regression (and, conversely, point out if it is). Can you briefly explain the purpose of ConvertTo-Xml with respect to my comments at the top, so I can open doc issues, if/as needed?

@SteveL-MSFT
Copy link
Member

@mklement0 I don't know the history of it, but I can make an educated guess. ConvertTo-Xml uses a simplified format that makes it easier to use with other systems that accept XML although it's probably still a bit more abstract than a simple property bag format... Export-CliXml is the same serialization format PowerShell uses for remoting so it's more complete to enable deserialization. Ideally, it seems like we should have had ConvertTo-Xml take a -Format parameter that supported CliXml and other xml formats rather than having this confusion between ExportTo-CliXml and ConvertTo-Xml having incompatible xml formats.

@mklement0
Copy link
Contributor Author

Thanks, @SteveL-MSFT.

other systems that accept XML

So I can suggest improvements to the docs: can you give examples of such other systems?
Are there common real-world scenarios?

@mklement0
Copy link
Contributor Author

I've created a docs issue at MicrosoftDocs/PowerShell-Docs#3310.

@sdwheeler
Copy link
Collaborator

@mklement0 @SteveL-MSFT this does seem specific to pscustomobject. The following works:

[psobject] @{ a = [psobject] @{ aa=11; bb=22 } } | ConvertTo-Xml

@mklement0
Copy link
Contributor Author

@sdwheeler: Yes, but do note that casting to [psobject] is a virtual no-op, because only the [pscustombject] cast provides the custom-object construction syntactic sugar:

PS> ([psobject] @{ a = [psobject] @{ aa=11; bb=22 } }).GetType().Name
Hashtable # !! [psobject] was effectively ignored.

As an aside: I say virtual no-op, because you do get an extra [psobject] wrapper, though that is mostly invisible - except when it isn't.

In other words: your command is the same as the following, and therefore operates on a hashtable:

@{ a = @{ aa=11; bb=22 } } | ConvertTo-Xml

@SteveL-MSFT
Copy link
Member

@mklement0 the "other systems" was purely hypothetical :) In this day and age, it's probably safe to say it's very uncommon to use XML vs JSON. Other than some demos, I've never had to use ConvertTo-Xml myself for any real world scenarios.

@IISResetMe
Copy link
Collaborator

IISResetMe commented Dec 9, 2018

Looks like the serializer erroneously decreases the serialization depth when writing PSObject properties:

This results in nested properties whenever there's more than one.

Removing --depth; seems to solve the problem completely

@SteveL-MSFT
Copy link
Member

@IISResetMe perhaps you could submit a PR with tests :)

IISResetMe added a commit to IISResetMe/PowerShell that referenced this issue Dec 16, 2018
WriteMemberInfoCollection() incorrectly nests sibling elements at depth==0
The reason seems to be that WriteMemberInfoCollection() calls WriteEndElement() at most once, even if `WriteStartElement()` has been called more than once
@iSazonov iSazonov added the Resolution-Fixed The issue is fixed. label Apr 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug Issue has been identified as a bug in the product Resolution-Fixed The issue is fixed. Up-for-Grabs Up-for-grabs issues are not high priorities, and may be opportunities for external contributors WG-Cmdlets-Utility cmdlets in the Microsoft.PowerShell.Utility module
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants