【问题标题】:Iterate through xml elements with powershell使用 powershell 遍历 xml 元素
【发布时间】:2012-07-26 23:36:57
【问题描述】:

我有一些具有不同元素的 xml 文件。我想用 c# 或 PowerShell 编写一些代码来遍历每个元素并获取值。 我希望它足够通用,以便我可以将它与其他 xml 文件一起使用。所有 xml 文件具有相同的格式,但元素的名称不同。

非常感谢您的帮助。

<root>
  <list>
       <FirstName>Abc</FirstName>
       <LastName>LT</LastName>
       <Occupatoin>Eng</Occupation>
       <BirthDate></BirthDate>
      ...
 </list>
</root>

----------------------
XML file 2

<root>
  <Trainings>
       <Java>Ab</Java>
       <NET>b</NET>
       <SQL>c</SQL>
       <Powershell>d</Powershell>
      ...
 </Trainings>
</root>

已经引入了另一个 xml,它将作为上述 xml 文件中元素迭代的基础。

根据下面每个元素的属性获取上面元素的值:

<root>
    <Element Name="Firstname />
    <Element Name="Lastname" />
    <Element Name="Occupation" />
    <Element Name="Java" />
    <Element Name="Net" />
...
</root>


[System.Xml.XmlDocument] $xdLists = new-object System.Xml.XmlDocument
[System.Xml.XmlDocument] $xdMig = new-object System.Xml.XmlDocument
$listfile = "C:\PowershellFiles\XmlLists.xml"
$xdLists.load($listfile)

$xdNodes= $xdLists.selectnodes("//DestinationLists/DestinationList")
$migCols = $xdLists.selectnodes("//MigrationColumns/Columns/Column")

#LOOP 1-----------------------------------------
foreach($xnode in $xdNodes)
{
    Write-Host $xnode.Attributes.GetNamedItem("MigrationFile").Value
    $destLists = $xnode.Attributes.GetNamedItem("Name").Value
    $migfiles = $xnode.Attributes.GetNamedItem("MigrationFile").Value
    
    
    Write-Host $destLists
    
    #Check if the xml file to read from exists
    
    if($migFiles -ne $null)
    {
            $xdMig.Load($migfiles)
        
            $spSite = Get-SPSite "http://sp2010:100" 
            $spWeb = $spSite.OpenWeb()

            $list = $spWeb.Lists[$destLists]

            foreach($nCol in $migCols)
            {
                $destListCol =  $nCol.Attributes.GetNamedItem("DestList").Value
                $sourcCol =  $nCol.Attributes.GetNamedItem("SourceCol").Value

#               Write-Host $col " - " $list.Title

                if($destListCol -eq $list.Title)
                {
                    Write-Host $destListCol " - " $list.Title " - Source Column: " $sourcCol  -ForegroundColor Green
                    Write-Host
                    
                    # ----------------------- time to search the exported lists --------------------
                    Write-Host "Search the exported list for the right column" -ForegroundColor  DarkYellow
                    
                    if($xdMig.DocumentElement -ne $null)
                        {
                            $xnList = $xdMig.DocumentElement.ChildNodes

                    #           LOOP 2----------------------------------------
                            Write-Host $xnList.Count " items found" -ForegroundColor Red
                            foreach($xn in $xnList)
                            {
                                Write-Host $xn.Name -ForegroundColor Red
                                
                                $nList = $xdMig.SelectNodes("//"+$xn.Name)
                                $lItem = $list.Items.Add()

                                foreach($n in $migCols)
                                  {
                                  
                                    if($n.Attributes -ne $null)
                                    {
                                        $sourceCol = $n.Attributes.GetNamedItem("SourceCol").Value
                                        $destCol = $n.Attributes.GetNamedItem("DestCol").Value
                                        $destList = $n.Attributes.GetNamedItem("DestList").Value
                                        
                                        Write-Host "Dest Col: " $destCol  "-  Sour Col: " $xn[$sourceCol].Name 
                                        Write-Host $destList -ForegroundColor Red

                                        if($list.Title -eq $destList)
                                        {
                                            if($xn[$sourceCol] -ne $null )
                                            {
                                                if($list.Fields[$destCol] -ne $null)
                                                {
                                                    $lItem[$destCol] = $xn[$sourceCol].InnerText    
                                                }
                                                        
                                            }else
                                            {
                                                Write-Host   $sourceCol " was not matched" -ForegroundColor Yellow
                                            }
                                        }
                                     }
                                  }
                                  $lItem.Update()
                                  Write-Host "-----------------------------------"
                            }

                        }
                }
            }
    }
}

【问题讨论】:

标签: c# xml powershell xpath sharepoint-2010


【解决方案1】:

您可以将 结合使用。假设您已修复 XML 错误并将 Element.Name 重命名为与数据文件中的大小写相同:

your_file.xml固定内容:

<root> 
  <list> 
       <FirstName>Abc</FirstName> 
       <LastName>LT</LastName> 
       <Occupation>Eng</Occupation> 
       <BirthDate></BirthDate> 
      ... 
 </list> 
</root>

index_file.xml固定内容:

<root> 
    <Element Name="FirstName" /> 
    <Element Name="LastName" /> 
    <Element Name="Occupation" /> 
    <Element Name="Java" /> 
    <Element Name="NET" /> 
... 
</root>

PoSH 映射他们:

$xmlIndex = [xml](gc ".\index_file.xml")
$xml = [xml](gc ".\your_file.xml")
$allValues = @{}; 

$xmlIndex.SelectNodes("//Element/@Name") | 
    %{ $nodeName = $_."#text"; $xml.SelectNodes("//$nodeName/text()") } |
    % { $allvalues[$_.ParentNode.ToString()] = $_.Value };

$allValues | ft

将跟随输出

Name                           Value
----                           -----
Occupation                     Eng
FirstName                      Abc
LastName                       LT

Name                           Value
----                           -----
NET                            b
Java                           Ab

【讨论】:

  • 嗨,akim,我怎样才能将上面的代码与 foreach 循环一起使用,以便我可以将返回的值添加到变量中
  • 将所有值添加到关联容器(也称为hash):$allValues = @{}; $xml.SelectNodes("//text()") | % { $allvalues[$_.ParentNode.ToString()] = $_.Value }; $allValues | ft
  • 您好,akim,非常感谢您的帮助。我只是在上面的问题中添加了一些内容。你能告诉我,只有在查询 XML 文件中指定了每个元素的值时,我才能显示该元素的值吗?
  • 嗨,akim,上面我添加了一些到目前为止我已经完成的代码。我很抱歉没有效仿你的榜样。我正在使用 xmldocument,因为我发现了一些可以正常工作的代码。我的代码问题是,如果我要添加 5 个 xml 文件,则最后一个 xml 的项目将被复制。知道我在那里做错了吗?感谢您的帮助。
  • 我不是 SharePoint 方面的专家,但您的示例看起来像是基于使用 $xdLists$xdMig 文件中提取值。如果是这样,$xmlIndex$xdLists$xml$xdMig。如果不是,请尝试以 PowerGui 之类的方式调试此代码,或将您的问题移至 appropriate section of forum
【解决方案2】:

我遇到了类似的需求,我需要深入研究不同的 XML 结构。这个递归例程适用于我遇到的大多数 xml。

function GetNodes($root,$j){
    $nodes=$root.ChildNodes
    $j++
    Foreach($child in $nodes){
       $tabs=""
       for ($i = 1; $i -lt $j; $i++){ $tabs+="`t"  }
       if ($child.NodeType -eq "Element"){
            $value=$root.($child.Name)
            if ($value.GetType().Name -eq "XmlElement"){
                write-host "$tabs$($child.Name)" -ForegroundColor green
            }else{
                write-host "$tabs$($child.Name): $($value)"
            }  
        }
        if ($child.HasChildNodes){ GetNodes $child $j }
    }
    $j--
}

[xml]$xml=get-content C:\Temp\test.xml
GetNodes $xml

文件 1 的输出如下所示

root
    list
        FirstName: Abc
        LastName: LT
        Occupation: Eng
        BirthDate: 

我将文件 1 和 2 组合起来得到这个输出:

root
    list
        FirstName: Abc
        LastName: LT
        Occupation: Eng
        BirthDate:
    Trainings
        Java: Ab
        NET: b
        SQL: c
        Powershell: d

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多