2012-08-14 70 views
1

我正在处理与以下内容类似的xml文件。但是,它是以下几千倍。我将使用powershell通过xml解析解析XML并查找字符串的所有实例

我需要找到字符串“c:\”出现的所有任务的任务名称。虽然这可能很容易,如果只有一个字符串可能显示区域,它可以完全显示在整个任务。在这个特定的任务中,我把C:\放在4个不同的时间。

,我希望能得到任务名称的输出,以及给定的路径被引用的地方......

<Task ID="00000000" Name="Task name goes here" Active="0" NextEID="22" CacheNames="random" AR="0" TT="COS"> 
     <Info> 
      <Description> 
      </Description> 
      <Notes> 
      </Notes> 
     </Info> 
     <Parameters> 
      <moreParameters>C:\pathGoesHere</moreParameters> 
     </Parameters> 
     <Schedules/> 
     <Source HostID="0" Type="FileSystem" Path="C:\path" FileMask="[Parm:parameter].txt" DeleteOrig="0" NewFilesOnly="0" SearchSubdirs="0" Unzip="0" RetryIfNoFiles="0" UseDefRetryCount="1" UseDefRetryTimeoutSecs="1" UseDefRescanSecs="1" UDMxFi="1" UDMxBy="1" ID="11"/> 
     <For ID="13"> 
      <Destination HostID="000000" Type="siLock" FolderID="" FolderType="4" FolderName="Home/[Parm:parameter]/" Subject="" FileName="[OnlyName]_[YYYY][MM][DD].bai" UseOrigName="0" ForceDir="1" OverwriteOrig="1" UseRelativeSubdirs="1" Zip="0" UseDefRetryCount="1" UseDefRetryTimeoutSecs="1" UseDefUser="1" UseDefClientCert="1" ID="12"/> 
      <If ID="14"> 
       <When> 
        <Criteria> 
         <comp a="[ErrorCodeFile]" test="NEQ" b="0"/> 
        </Criteria> 
        <UpdOrig Action="d" ID="15"/> 
        <Destination HostID="0000000000" Type="Share" Path="C:\anotherCPath" FileName="[Parm:parameter]_[YYYY][MM][DD].bai" UseOrigName="0" ForceDir="1" OverwriteOrig="1" UseRelativeSubdirs="1" Zip="0" UseDefRetryCount="1" UseDefRetryTimeoutSecs="1" ID="17"/> 
       </When> 
      </If> 
     </For> 
     <If ID="19"> 
      <When> 
       <Criteria> 
        <comp a="[ErrorCodeTask]" test="NNE" b="0"/> 
       </Criteria> 
       <Email HostID="385322183" Subject="[TaskStatus]-[TaskName]" Message="" AddressTo="[email protected]" Attachment = "C:\path\" UseDefRetryCount="1" UseDefRetryTimeoutSecs="1" ID="20"/> 
      </When> 
     </If> 
    </Task> 
+0

您正在使用哪种语言? – Dave 2012-08-14 16:49:38

+0

powershell。对不起 – mhopkins321 2012-08-14 16:50:14

回答

6

假设XML位于file.xml,以下XPath与回报你Name属性: 字符串 “C:\” 可能是在:

//Task[contains(text(), "C:\") or //*[contains(text(), "C:\")] or //*[@*[contains(., "C:\")]]]/@Name 

说明:

    文本 Task标签
  • 文本任何儿童
  • 在任何儿童的任何属性

PowerShell的样本:

#read xml 
$xml = [xml](gc -Encoding utf8 .\test.xml) 

#process it 
$xml | 
    Select-Xml '//Task[contains(text(), "C:\") or //*[contains(text(), "C:\")] or //*[@*[contains(., "C:\")]]]/@Name' | 
    % { $_.Node."#text" } 
+0

我希望我能给你100个绿色的复选标记! – mhopkins321 2012-08-14 17:52:00

+0

我刚才看到这个答案产生了超过1400条记录的文本文件,因此节省了我几个小时的手工工作。看起来像我可以采取休息一周休息:-P – mhopkins321 2012-08-14 17:57:35

+0

thx,如果你熟悉Xpath,你可以做更多 – Akim 2012-08-15 04:37:34

1

当你施放到[XML],您可以访问一切都使用非常好的“属性”语法。具有相同标签的多个节点将作为数组公开。然后,您可以使用InnerXml属性获取定义当前节点的原始XML字符串。然后您只需要对您的搜索字符串进行简单的“类似”匹配。

假设你有下一个“任务”节点的多个“任务”节点在一个文件中:

$tasks = [xml] (Get-Content .\Tasks.xml) 
$tasks.Tasks.Task |?{ $_.InnerXml -like '*C:\*' } | select -expand Name 

或者,如果在每个多个文件的单个任务节点:

dir *.xml |%{ [xml] (Get-Content $_) } |?{ $_.Task.InnerXml -like '*C:\*' } | select -expand Name 

这些将为您提供任务名称。获取包含搜索字符串的节点中的每一行都有点棘手。这是一个黑客正则表达式的方法(我知道我知道,不要用正则表达式解析XML ...)。同样,假设每个XML文件中有一个Task节点:

$taskXmls = dir *.xml |%{ [xml](Get-Content $_) } 

foreach($taskXml in $taskXmls) 
{ 
    if($taskXml.Task.InnerXml -like '*C:\*') 
    { 
     $hits = [Regex]::Matches($taskXml.Task.InnerXml, '<[^<]*C:\\[^>]*>') 
     $hitList = $null 
     if($hits) 
     { 
      $hitList = $hits | select -expand Value 
     } 
     new-object psobject -prop @{TaskName = $taskXml.Task.Name; Hits = $hitList} 
    } 
}