【问题标题】:How do I get a list of all of the XML tags in a file using PowerShell and Regular Expressions?如何使用 PowerShell 和正则表达式获取文件中所有 XML 标记的列表?
【发布时间】:2018-08-04 00:46:28
【问题描述】:

这个问题与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 命令,但它给了我太多反馈。我只想要一个主“匹配”列表。

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 不是最好的使用方法,但在找到这篇 Microsoft 帖子后,我觉得我已经接近我的解决方案了: 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标记。

【问题讨论】:

  • 您是否有特定原因要使用 RegEx? PowerShell 支持 XML 看到这篇文章https://stackoverflow.com/questions/13732715/loop-through-xml-elements
  • 没有具体原因。我认为 RegEx 将是一个好的开始,因为我什至不确定该文件是否是有效格式的 XML 文档。我现在正在看那个帖子,试图理解它。
  • 就像我在帖子前面提到的那样,我根本不使用 PowerShell,在花了半小时阅读和重读该建议帖子之后,我无法让它为我吐出结果。我得到的只是错误。
  • 我建议您使用HtmlAgilityPack 来解析您的文档。它也适用于 XML,最重要的是它可以很好地处理格式错误的文档。 RegEx 不能很好地替代真正的解析器;你不应该使用它。如果您的 XML 中缺少的只是 &lt;?xml 标记,那么只需添加它并使用内置类型。
  • briantist 的建议听起来不错。我完全同意正则表达式是第三方解析器的糟糕替代品。通常有一些你不会涵盖的边缘情况。我最初的假设是你有有效的 xml。但是你甚至不能确定它使正则表达式几乎不可能。并且使用第三方解析器很困难。纠正简单的无错误代码需要控制输入质量。

标签: regex xml powershell


【解决方案1】:

至于……

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

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

请参阅这篇文章,了解提供一些学习 PowerShell 的途径的人。

有人有教别人powershell的经验吗?

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

当然你可以用 RegEx 来做,但最好在本地处理它。

在 PowerShell 中,XML 很重要;和 JSON 一样。所有帮助文件都只是 XML 文件。有内置的 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 PSObject。我发现有一些 sn-ps 可以做到这一点,但不是我在这个练习中需要的方式。在本例中,我从 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

带有节点/元素的智能/自动完成...

$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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 2019-07-04
    • 2011-10-21
    • 2015-02-08
    • 1970-01-01
    相关资源
    最近更新 更多