通过具有未知结构和大小的xml树进行迭代(对于xml到注册表)

时间:2016-05-12 20:52:27

标签: xml powershell xpath

提前致谢。我有一个未知结构和不同元素的xmldocument。我想遍历获取元素名称的所有元素,并最终将xml文档重建为注册表项和值

例如

<Root>
  <Names>
    <Name>Bob</Name>
  </Names>
  <Locations>
    <States>
      <State>Ohio</State>
      <State>Michigan</State>
      <State>
        Florida
        <WeatherType>Hot</WeatherType>
      </State>
    </States>
  </Locations>
</Root>

输出将包括每个元素值的xpath(我将用于reg路径)(我将用于reg键值)。输出看起来像这样。

Root\Names\Name = Bob
Root\Locations\States\State = Ohio
Root\Locations\States\State = Michigan
Root\Locations\States\State = Florida
Root\Locations\States\State\Florida\WeatherType = Hot

2 个答案:

答案 0 :(得分:1)

您正在寻找的输出不是xpath。防爆。 WeatherType - 节点的xpath为Root/Locations/States/State[contains(text(),'Florida')]/WeatherType

为了得到你要求的东西,我会这样做:

  1. 查找具有文本值的所有节点
  2. 获取父节点的路径
    • 当存在相同类型的兄弟姐妹(元素名称)时,将文本值添加到路径,例如的状态。
  3. 输出path = text-value
  4. 例如:

    #$xml = [xml](Get-Content -Path myfile.xml)
    $xml = [xml]@"
    <Root>
      <Names>
        <Name>Bob</Name>
      </Names>
      <Locations>
        <States>
          <State>Ohio</State>
          <State>Michigan</State>
          <State>
            Florida
            <WeatherType>Hot</WeatherType>
          </State>
        </States>
      </Locations>
    </Root>
    "@
    
    #Get nodes with text-value
    $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())"
    }
    

    输出:

    Root\Names\Name = Bob
    Root\Locations\States\State = Ohio
    Root\Locations\States\State = Michigan
    Root\Locations\States\State = Florida
    Root\Locations\States\State\Florida\WeatherType = Hot
    

答案 1 :(得分:0)

以下是对“ Frode F”代码的略微修改:


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
        }

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

这考虑到了我在使用上述代码时遇到的错误情况。