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

问题描述 投票:2回答:2

我有一个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>

我需要找到带有value =“27606_ManufacturingProcess8”的ManufacturingProcessID属性,如果我找到它然后查看同一节点下的ProcessStatusID属性,如果值=“psClosed”,那么我需要将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
           }
         }

       }
    }
}
powershell xml-parsing
2个回答
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>

然后代码将识别是否存在具有名称“ManufacturingProcessID”的Property元素设置为值“27606_ManufacturingProcess8”的任何“Object”节点,而在同一节点中,名称“ProcessStatusID”设置为值“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
投票

Stanislav Castek's answerSelect-Xml在正确的轨道上,<Object>支持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..." } 元素 - 稍后 - 在管道中进行慢速处理,您可以使用单个XPath表达式执行整个查询:

Select-Xml

请注意Get-ChildItem如何直接从ForEach-Object接受文件输入。 仅为XPath查询返回匹配的输入文件输入qazxswpoi脚本块。

© www.soinside.com 2019 - 2024. All rights reserved.