2012-07-28 108 views
1

我有一些xml文件具有不同的元素。我想写一些代码在C#或PowerShell中遍历每个元素并获取值。 我希望它足够通用,以便我可以将它与其他xml文件一起使用。所有xml文件都具有相同的格式,但元素的名称延迟。使用PowerShell遍历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 "-----------------------------------" 
          } 

         } 
       } 
      } 
    } 
} 
+0

http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts – Kiquenet 2013-03-06 10:01:03

回答

2

您可以用结合

上述基于以下各元素的属性得到元素的值。假设你有固定的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映射” em:

$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 
+0

嗨akim,我如何在foreach循环中使用上面的代码,以便将返回的值添加到变量中 – 2012-07-28 15:43:18

+1

全部添加值_associat ive container_(也称为_hash_):'$ allValues = @ {}; $ xml.SelectNodes(“// text()”)| %{$ allvalues [$ _。ParentNode.ToString()] = $ _。Value}; $ allValues |英尺' – Akim 2012-07-28 15:57:01

+0

嗨阿基姆,非常感谢您的帮助。我刚刚在上面的问题中添加了一些内容。你能告诉我怎么才能显示每个元素的值,只有当查询XML文件中指定了该元素时? – 2012-07-28 20:22:35

0

我跑进地方,我需要深入到不同的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