如何在 Powershell 中显示整个 XML 树?

How do I display an entire XML tree in Powershell?

我正在寻找一种方法来遍历基于 XML API 的响应并按以下格式显示整个 XML 树:

node\node = VALUE
node\node\node = VALUE
node\node\node2 = VALUE

我有一个脚本适用于某些 XML 输出但在其他输出上失败:

    function Get-XMLTree($xml) {
        $nodesWithText = $xml.SelectNodes("//*[text()]")
    
        foreach($node in $nodesWithText) {
            #Start with end of path (element-name of the node with text-value)
            $path = $node.LocalName
            
            #Get parentnode
            $parentnode = $node.ParentNode
    
            #Loop until document-node (parent of root-node)
            while($parentnode.LocalName -ne '#document') {
    
                #If sibling with same LocalName (element-name) exists
                if(@($parentnode.ParentNode.ChildNodes | Where-Object { $_.LocalName -eq $parentnode.LocalName }).Count -gt 1){
                    #Add text-value to path
                    $path = "{0}$path" -f ($parentnode.'#text').Trim()
                }
    
                #Add LocalName (element-name) for parent to path
                $path = "$($parentnode.LocalName)$path"
    
                #Go to next parent node
                $parentnode = $parentnode.ParentNode
            }
    
            #Output "path = text-value"
            "$path = $(($node.'#text').Trim())"
        }
    }

对于某些 XML 的回复,这可以顺利进行。对于其他人,我收到类似于以下的错误:

InvalidOperation: /script1.ps1:51:17
Line |
  51 |                  $path = "{0}$path" -f ($parentnode.'#text').Trim()
     | You cannot call a method on a null-valued expression.

感谢任何帮助

XSLT 似乎是这项工作从 xml 格式中提取信息的工具。

This answer 给出了如何在 powershell 中应用 xslt 的要点。 或者,使用许多其他 XSLT tools ....

之一

正如@mclayton 所问 - 如果您可以提供原始 xml,有人可能会为您提供快速 xslt 以提取您正在寻找的信息。

已修复!这是最终函数


function Get-XMLTree($xml) {
    $nodesWithText = $xml.SelectNodes("//*[text()]")
    foreach($node in $nodesWithText)
    {    
        #Start with end of path (element-name of the node with text-value)
        $path = $node.LocalName

        #Get parentnode
        $parentnode = $node.ParentNode

        #Loop until document-node (parent of root-node)
        while($parentnode.LocalName -ne '#document')
        {
            #If sibling with same LocalName (element-name) exists
            if(@($parentnode.ParentNode.ChildNodes | Where-Object { $_.LocalName -eq $parentnode.LocalName }).Count -gt 1)
            {
                #Add text-value to path
                if($parentnode.'#text')
                {
                    $path = "{0}$path" -f ($parentnode.'#text').Trim()
                }
            }

            #Add LocalName (element-name) for parent to path
            $path = "$($parentnode.LocalName)$path"

            #Go to next parent node
            $parentnode = $parentnode.ParentNode
        }

        #Output "path = text-value"
        "$path = $(($node.'#text').Trim())"
    }
}