3

次のような xml ファイルを使用しています。ただし、次の数千回オーバーです。私はxmlを解析するためにpowershellを使用します

文字列「c:\」が表示されるすべてのタスクのタスク名を見つける必要があります。文字列が表示される領域が 1 つしかない場合は簡単ですが、文字列はタスク全体に表示される可能性があります。この特定のタスクでは、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@address.com" Attachment = "C:\path\" UseDefRetryCount="1" UseDefRetryTimeoutSecs="1" ID="20"/>
            </When>
        </If>
    </Task>
4

2 に答える 2

7

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" }
于 2012-08-14T17:14:35.120 に答える
1

[xml] にキャストすると、非常に優れた「プロパティ」構文を使用してすべてにアクセスできます。同じタグを持つ複数のノードは配列として公開されます。次に、InnerXml プロパティを使用して、現在のノードを定義する生の XML 文字列を取得できます。次に、検索文字列に対して単純な「-like」マッチを実行するだけです。

1 つのファイルの単一の「タスク」ノードの下に複数の「タスク」ノードがあると仮定します。

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

または、複数のファイルのそれぞれに単一の Task ノードがある場合:

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}
   }
}
于 2012-08-15T20:05:14.550 に答える