如何使用PowerShell和正则表达式获取文件中所有XML标记的列表?

时间:2018-02-23 21:48:44

标签: regex xml powershell

此问题与RegEx find all XML tags有关,但我尝试在Windows PowerShell中执行此操作。

我有一个包含许多不同XML标记的XML文件,文件很大,所以基本上我想使用RegEx来解析文件并将所有标记的名称作为列表吐出。 XML文档不是有效的XML文档,即使它包含XML标记和元素。因此,使用PowerShell的XML函数不会起作用。尝试将其视为XML文档时出现了很多错误,因此需要使用RegEx。

我已确定以下RegEx标识了代码(感谢上述相关问题):(?<=<)([^\/]*?)((?= \/>)|(?=>))

这是我正在解析的文件的一个非常小的片段:

<data><bp_year /><bp_make>John Deere</bp_make><bp_model>650</bp_model><bp_price>3000.00</bp_price><bp_txtDayPhone>555-555-5555</bp_txtDayPhone><bp_bestPrice>3000.0000</bp_bestPrice><bp_txtComments>Best price available?</bp_txtComments><bp_url>https://www.example.com</bp_url></data>
<data><receiveOffers /><link>http://example.com/inventory.htm?id=2217405&amp;used=1</link><itemName>2007 Yamaha RHINO 660</itemName></data>
<data><vehicleYear>2008</vehicleYear><vehicleMake>Buick</vehicleMake><vehicleModel>Enclave</vehicleModel><vehicleStyle>CX</vehicleStyle><vehicleInformation /><vehicleMileage /><phone>555-555-5555</phone><timeOfDay>Morning</timeOfDay><message /></data>
<data><mo_year>2009</mo_year><mo_make>Webasto</mo_make><mo_model>Air Top 2000</mo_model><mo_price /><mo_txtDayPhone>555-555-5555</mo_txtDayPhone><mo_txtOffer>700</mo_txtOffer><mo_txtTrade /><mo_txtComments /></data>

我真的不具备使用Powershell的经验,但根据我的理解,你可以用它做Grep的东西。在互联网上搜索之后,我找到了一些资源,通过使用powershell Select-String命令帮助我找到解决方案。

我尝试了以下powershell命令,但它给了我太多反馈。我只想要一个大师&#34;匹配&#34;列表。

Select-String -Path '.\dataXML stuff - Copy.xml'-Pattern "(?<=<)([^\/]*?)((?= \/>)|(?=>))" -AllMatches | Format-List -Property Matches

生成的输出示例:

Matches : {data, vehicleYear, vehicleMake, vehicleModel...}
Matches : {data, address, city, region...}
Matches : {data, vehicleYear, vehicleMake, vehicleModel...}
Matches : {data, vehicleYear, vehicleMake, vehicleModel...}
Matches : {data, address, city, region...}
Matches : {data, vehicleYear, vehicleMake, vehicleModel...}
Matches : {data, vehicleYear, vehicleMake, vehicleModel...}
Matches : {data, mo_year, mo_make, mo_model...}

基本上,我想要这样的东西:

data
vehicleYear
vehicleMake
vehicleModel
address
city
region
mo_year
mo_make
mo_model

依此类推......

只返回并列出匹配的字符串,而不是告诉我在XML文件的每一行上匹配的内容。我更喜欢列表格式,因为我可以将它泵入Excel并获得一个明确的标签名称列表,然后开始实际做我需要完成的事情,但是绝大多数不同的XML标签并且不知道它们是什么让我抓住了起来。

也许Select-String并不是最好用的方法,但我觉得在找到这篇微软帖子之后我已经接近我的解决方案了: https://social.technet.microsoft.com/Forums/windowsserver/en-US/d5bbd2fb-c8fa-43ed-b432-79ebfeee82ea/return-only-matches-from-selectstring?forum=winserverpowershell

基本上,这里的解决方案经过修改以满足我的需求:

Gc 'C:\Documents\dataXML stuff - Copy.xml'|Select-String -Pattern "(?<=<)([^\/]*?)((?= \/>)|(?=>))"|foreach {$_.matches}|select value 

它提供了所有xml标记的列表,就像我想要的那样,除了它只返回该行的第一个XML标记,所以我得到了很多:

data
data
data

但没有vehicleYear,vehicleMake,vehicleModel等,这将是该行的第2或第3或第11个xml标签。

1 个答案:

答案 0 :(得分:2)

至于......

  

就像我之前在帖子中提到的那样,我根本不使用PowerShell

阅读是一件好事,但看到它在行动中会更好。有许多免费的视频资源可以从一开始就查看PowerShell,以及大量的参考资料。然后是要利用的MS TechNet虚拟实验室。

请参阅此帖子,了解为学习PowerShell提供一些途径的人。

  

有没有人有教过别人权力的经验?

     
    

https://www.reddit.com/r/PowerShell/comments/7oir35/help_with_teaching_others_powershell

  

当然可以使用RegEx来完成它,但最好是本地处理它。

在PowerShell中,XML是一个大问题;和JSON一样。所有帮助文件只是一个XML文件。有一些bulit-in cmdlet来处理它。

# Get parameters, examples, full and Online help for a cmdlet or function

Get-Command -Name '*xml*' | Format-Table -AutoSize

(Get-Command -Name Select-Xml).Parameters
Get-help -Name Select-Xml -Examples
Get-help -Name Select-Xml -Full
Get-help -Name Select-Xml -Online

Get-Help about_*

# Find all cmdlets / functions with a target parameter
Get-Help * -Parameter xml

# All Help topics locations
explorer "$pshome\$($Host.CurrentCulture.Name)"

许多网站都提供有关处理它的文章。

  

PowerShell数据基础知识:XML

     

要掌握PowerShell,您必须知道如何使用XML。 XML是一种重要的数据交换格式,因为它仍然是确保保留对象数据的最可靠方法。幸运的是,正如Michael Sorens演示的那样,PowerShell使这一切变得简单。

     

https://www.red-gate.com/simple-talk/sysadmin/powershell/powershell-data-basics-xml

     

将XML转换为PowerShell PSObject

     

最近,我正在研究一些代码(当然)并且需要将一些XML转换为PowerShell PSObjects。我在那里找到了一些片段,但这不是我练习这个练习所需的方式。在这种情况下,我正在从Plex转换XML元数据。

     

https://consciouscipher.wordpress.com/2015/06/05/converting-xml-to-powershell-psobject

     

掌握PowerShell中的日常XML任务

     

PowerShell具有出色的XML支持。一开始并不是很明显,但是在PowerShellMagazine.com的朋友们的帮助下,您很快就会解决日常的XML任务 - 甚至是非常复杂的任务。

     

因此,让我们看一下如何使用非常简单的PowerShell代码来完成以前在PowerShell之前的时代那么令人费解的事情。

     

http://www.powershellmagazine.com/2013/08/19/mastering-everyday-xml-tasks-in-powershell

对于所有意图和目的,如果我只为您的样本选择一行,并使用.Net xml命名空间执行此操作...

($MyXmlData = [xml]'<data><bp_year /><bp_make>John Deere</bp_make><bp_model>650</bp_model><bp_price>3000.00</bp_price><bp_txtDayPhone>555-555-5555</bp_txtDayPhone><bp_bestPrice>3000.0000</bp_bestPrice><bp_txtComments>Best price available?</bp_txtComments><bp_url>https://www.example.com</bp_url></data>')

data
----
data

你得到这样的结果......

$MyXmlData.data

bp_year        : 
bp_make        : John Deere
bp_model       : 650
bp_price       : 3000.00
bp_txtDayPhone : 555-555-5555
bp_bestPrice   : 3000.0000
bp_txtComments : Best price available?
bp_url         : https://www.example.com

使用intellisene /自动完成节点/元素...

$MyXmlData.data.bp_year

另一种观点......

$MyXmlData.data | Format-Table -AutoSize

bp_year bp_make    bp_model bp_price bp_txtDayPhone bp_bestPrice bp_txtComments        bp_url                 
------- -------    -------- -------- -------------- ------------ --------------        ------                 
        John Deere 650      3000.00  555-555-5555   3000.0000    Best price available? https://www.example.com

然后,只需设置标签/名称

$MyXmlData.data.ChildNodes.Name

bp_year
bp_make
bp_model
bp_price
bp_txtDayPhone
bp_bestPrice
bp_txtComments
bp_url

所以,配备上述方法/说明。只需循环浏览您的文件即可获得您所追求的一切。

因此,只需将您的样本转储到一个没有更改的文件中,就可以做到这一点。

$MyXmlData = (Get-Content -Path 'D:\Scripts\MyXmlData.xml')

$MyXmlData | Format-List -Force

ForEach($DataRow in $MyXmlData)
{
    ($DataObject = [xml]$DataRow).Data | Format-Table -AutoSize

}

bp_year bp_make    bp_model bp_price bp_txtDayPhone bp_bestPrice bp_txtComments        bp_url                 
------- -------    -------- -------- -------------- ------------ --------------        ------                 
        John Deere 650      3000.00  555-555-5555   3000.0000    Best price available? https://www.example.com



receiveOffers link                                               itemName             
------------- ----                                               --------             
              http://example.com/inventory.htm?id=2217405&used=1 2007 Yamaha RHINO 660



vehicleYear vehicleMake vehicleModel vehicleStyle vehicleInformation vehicleMileage phone        timeOfDay message
----------- ----------- ------------ ------------ ------------------ -------------- -----        --------- -------
2008        Buick       Enclave      CX                                             555-555-5555 Morning          



mo_year mo_make mo_model     mo_price mo_txtDayPhone mo_txtOffer mo_txtTrade mo_txtComments
------- ------- --------     -------- -------------- ----------- ----------- --------------
2009    Webasto Air Top 2000          555-555-5555   700    



ForEach($DataRow in $MyXmlData)
{
    ($DataObject = [xml]$DataRow).Data.ChildNodes.Name

}


bp_year
bp_make
bp_model
bp_price
bp_txtDayPhone
bp_bestPrice
bp_txtComments
bp_url
receiveOffers
link
itemName
vehicleYear
vehicleMake
vehicleModel
vehicleStyle
vehicleInformation
vehicleMileage
phone
timeOfDay
message
mo_year
mo_make
mo_model
mo_price
mo_txtDayPhone
mo_txtOffer
mo_txtTrade
mo_txtComments

但是,请注意,这不是唯一的方法。