解析XML并查找字符串的所有实例
我正在处理一个xml文件,它看起来类似于以下内容。然而,它是以下数千倍以上。我将使用powershell解析xml 我需要找到显示字符串“c:\”的所有任务的任务名称。虽然如果字符串只显示一个区域,这可能很容易,但它可以完全显示在整个任务中。在这个特殊的任务中,我将C:\放在了4个不同的时间 我希望得到任务名称的输出,以及给定路径被引用的位置解析XML并查找字符串的所有实例,xml,powershell,csv,Xml,Powershell,Csv,我正在处理一个xml文件,它看起来类似于以下内容。然而,它是以下数千倍以上。我将使用powershell解析xml 我需要找到显示字符串“c:\”的所有任务的任务名称。虽然如果字符串只显示一个区域,这可能很容易,但它可以完全显示在整个任务中。在这个特殊的任务中,我将C:\放在了4个不同的时间 我希望得到任务名称的输出,以及给定路径被引用的位置 <Task ID="00000000" Name="Task name goes here" Active="0" NextEID="22" Cac
<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>
C:\PathGoesher
假设XML位于file.XML
,在XPath
之后,返回Name
属性:
字符串“C:\”可能位于:
//Task[contains(text(), "C:\") or //*[contains(text(), "C:\")] or //*[@*[contains(., "C:\")]]]/@Name
说明:
标记任务的文本
- 任何儿童的文本
- 在任何子对象的任何属性中
#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" }
当您转换为[xml]时,您可以使用非常好的“属性”语法访问所有内容。具有相同标记的多个节点将作为阵列公开。然后可以使用InnerXml属性获取定义当前节点的原始XML字符串。然后只需对搜索字符串进行简单的“-like”匹配 假设在一个文件中的单个“任务”节点下有多个“任务”节点:
$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
这些将为您获取任务名称。获取节点中包含搜索字符串的每一行有点棘手。这里有一个hacky-regex方法(我知道我知道,不要用regex解析XML…)。同样,假设每个XML文件中都有一个任务节点:
$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}
}
}
$taskXmls=dir*.xml |%{[xml](获取内容$}
foreach($taskXml中的$taskXmls)
{
if($taskXml.Task.InnerXml-类似“*C:\*”)
{
$hits=[Regex]::匹配($taskXml.Task.InnerXml,“”)
$hitList=$null
如果($hits)
{
$hitList=$hits |选择-展开值
}
新对象psobject-prop@{TaskName=$taskXml.Task.Name;Hits=$hitList}
}
}
您使用的是哪种语言?我刚刚看到这个答案生成了一个包含1400多条记录的文本文件,从而节省了我数小时的手工工作。看起来我可以休息一周了:-PI稍微更改了代码$parsedData=$xml |选择xml!'//任务[包含(text(),“C:\”)或//*[包含(text(),“C:\”)或//*[@*[包含(,!“C:\”)]]/@Name'\%{$\节点。“\文本”};添加内容“c:\path\tasksWithC.txt”$parsedData
,但文本文件仅包含所有任务的列表。包括那些不包含C的文件:\如果我只是想把每个人都写到它自己的单独文件中,我该怎么做呢?类似这样:gci-recurse-include*.xml |%{PARSE file HERE}