Powershell XML选择具有特定值的节点

时间:2018-02-09 20:00:34

标签: powershell xml-parsing

我有一个包含;

的XML文件
<?xml version="1.0"?>
<JobContainer version="2017-1">
  <Object name="MainObject" type="TDM_Container">
    <Object name="OrderList" type="TDM_List_Order">
      <List name="Items">
        <Object type="TDM_Item_Order">
          <Property name="IntOrderID" value="3I-390049-SZEPLOUSKI-793269"/>
        </Object>
      </List>
    </Object>
    <Object name="ModelJobList" type="TDM_List_ModelJob">
      <List name="Items">
        <Object type="TDM_Item_ModelJob">
          <Property name="ModelJobID" value="MJ5393C2FF84844DE38BC481CB5AD36D93"/>
        </Object>
      </List>
    </Object>
        <Object type="TDM_Item_ModelElement">
          <Property name="ModelJobID" value="MJ5393C2FF84844DE38BC481CB5AD36D93"/>
          <Property name="ProcessStatusID" value="psScanned"/>
          <Property name="ProcessLockID" value="plReady"/>
          <Property name="ManufacturingProcessID" value="57435_ManufacturingProcess17"/>
          <Property name="ManufacturerID" value="27606"/>
        </Object>
        <Object type="TDM_Item_ModelElement">
          <Property name="ModelJobID" value="MJ5393C2FF84844DE38BC481CB5AD36D93"/>
          <Property name="ProcessStatusID" value="psClosed"/>
          <Property name="ProcessLockID" value="plReady"/>
          <Property name="ManufacturingProcessID" value="27606_ManufacturingProcess8"/>
          <Property name="ManufacturerID" value="27606"/>
        </Object>
        <Object type="TDM_Item_ModelElement">
          <Property name="ModelJobID" value="MJ5393C2FF84844DE38BC481CB5AD36D93"/>
          <Property name="ProcessStatusID" value="psScanned"/>
          <Property name="ProcessLockID" value="plReady"/>
          <Property name="ManufacturingProcessID" value="57435_ManufacturingProcess17"/>
          <Property name="ManufacturerID" value="27606"/>
        </Object>
      </List>
    </Object>
    <Object name="ElementList" type="TDM_List_Element">
      <List name="Items">
        <Object type="TDM_Item_Element">
          <Property name="Anatomical" value="False"/>
        </Object>
      </List>
    </Object>
  </Object>
</JobContainer>

我需要找到带有值=&#34; 27606_ManufacturingProcess8&#34;的ManufacturingProcessID属性,如果我找到它,那么查看同一节点下的ProcessStatusID属性,如果值=&#34; psClosed&# 34;然后我需要将xml文件移动到另一个文件夹。

我的代码在下面工作,但它只在节点是第一个时才起作用。但有时节点不是第一个节点。如果该节点不是第一个节点,我该如何找到它。

Get-ChildItem $sSourceFolder | ForEach-Object -Process {
    if ($_.PSIsContainer)
    {
       # Store subfolder path in a variable
       $sFolderPath = $_.FullName
       $sFolderName = Split-Path $sFolderPath -Leaf

       Get-ChildItem $sFolderPath | Where {$_.Name -like $sFolderName + '.xml'} | foreach{

         $sFilepath = $_.FullName

         [xml]$xml2 = Get-Content $sFilepath

         $sValueMPI = $xml2.SelectNodes('//Property') | ?{$_.name -eq "ManufacturingProcessID"} | select -First 1 -ExpandProperty value

         if ($sValueMPI -eq '27606_ManufacturingProcess8')
         {

           $sValue = $xml2.SelectNodes('//Property') | ?{$_.name -eq "ProcessStatusID"} | select -First 1 -ExpandProperty value

           if ($sValue -eq 'psClosed')
           {

             # If destination folder already exists, add sequential suffix like (1), (2), etc.
             if (Test-Path ($sDestFolder + $sFolderName))
             {
                $j = 1
                While (Test-Path ($sDestFolder + "$sFolderName($j)"))
                {
                   $j = $j + 1
                }
                $sFolderName = "$sFolderName($j)"
             }

             # Move folder to archive destination
             Move-Item $sFolderPath ($sDestFolder + $sFolderName) -ErrorVariable MoveError -Verbose -Force *>> $sLogPath
             if (!($MoveError)) {$i = $i + 1} #if no move error,  then increment counter
           }
         }

       }
    }
}

2 个答案:

答案 0 :(得分:1)

您应该寻找父节点并深入挖掘它。不确定您的XML文件的外观,因为您没有发布上面的有效代码。但是,让它看起来像下面那个

<Object type="TDM_Item_ModelElement">
  <Property name="ModelElementID" value="MEC35A1D182F984AE893952151DA417D51"/>
  <Property name="ModelJobID" value="MJ5393C2FF84844DE38BC481CB5AD36D93"/>
  <Property name="MaterialID" value="26167_Ti (xyz)"/>
  <Property name="ColorID" value=""/>
  <Property name="ProcessStatusID" value="psClosed"/>
  <Property name="AltProcessStatusID" value="psClosed"/>
  <Property name="ProcessLockID" value="plReady"/>
  <Property name="ManufacturingProcessID" value="27606_ManufacturingProcess8"/>
  <Property name="ManufacturerID" value="27606"/>
</Object>

然后代码将识别是否有任何'Object'节点具有名称为“ManufacturingProcessID”的Property元素设置为Value“27606_ManufacturingProcess8”,而在同一节点中,名称为“ProcessStatusID”的属性设置为Value“psClosed”以下。把它写成一个单行,所以它读起来有点乱,但它的作用是通过$ xml2内容查找父元素“Object”,其中所有“Property”元素都是嵌套的,然后它检查属性是否与上述名称具有所需的值。如果找到至少一个节点,那么您点击了您想要存档的XML文件或者什么;)

$validNodes = $xml2 | Select-Xml -XPath '//Object' | %{$_ | ?{((($_.Node.Property.Name -eq "ManufacturingProcessID") -and ($_.Node.Property.Value -eq "27606_ManufacturingProcess8")) -and (($_.Node.Property.Name -eq "ProcessStatusID") -and ($_.Node.Property.Value -eq "psClosed")))}}
if ($validNodes.Count -gt 0) { ... Do your file operation ....}

希望它有所帮助!

答案 1 :(得分:1)

by generating and executing INSERT statements Select-Xml 的正确轨道上,它支持XPath查询,但不是仅使用query {提取更高级别的<Object>元素{1}}以后 - 在管道中进行慢速处理,您可以使用单个XPath表达式执行整个查询

//Object

请注意# Formulate the XPath query $xpathQuery = '//Property[@value="{0}"]/../Property[@value="{1}"]' -f '27606_ManufacturingProcess8', 'psClosed' # ... Get-ChildItem -File $sFolderPath -Filter ($sFolderName + '.xml') | Select-Xml $xPathQuery | ForEach-Object { $file = $_.Path # full path of the input file # Perform the move... Write-Verbose -Verbose "Moving $file..." } 如何直接从Select-Xml接受文件输入 只会为XPath查询返回匹配项的输入文件输入Get-ChildItem脚本块。