gpt4 book ai didi

xml - 使用 PowerShell 解析带有命名空间的 XML

转载 作者:行者123 更新时间:2023-12-03 17:10:06 27 4
gpt4 key购买 nike

我需要一些帮助来理解 PowerShell 中的 XML。
我有几个这样的 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.example.com/xml/catalog/2006-10-31">
<product product-id="11210">
...
<available-flag>true</available-flag>
<online-flag>false</online-flag>
<online-flag site-id="ru">true</online-flag>
<online-flag site-id="fr">true</online-flag>
<online-flag site-id="uk">false</online-flag>
<online-flag site-id="de">true</online-flag>
...
</product>
<product product-id="50610">
...
<available-flag>true</available-flag>
<online-flag>true</online-flag>
<online-flag site-id="ru">false</online-flag>
<online-flag site-id="fr">true</online-flag>
<online-flag site-id="uk">false</online-flag>
<online-flag site-id="de">fasle</online-flag>
...
</product>
<product product-id="82929">
...
<available-flag>true</available-flag>
<online-flag>true</online-flag>
<online-flag site-id="ru">false</online-flag>
<online-flag site-id="fr">true</online-flag>
<online-flag site-id="uk">false</online-flag>
<online-flag site-id="de">true</online-flag>
...
</product>
</catalog>

我需要在 PowerShell 中获取两个元素的值:
  • <online-flag> (没有 site-id 属性)
  • <online-flag site-id="ru">

  • 对于带有 product-id="50610" 的产品.

    我有以下代码:
    $Path = "C:\Temp\0\2017-08-12_190211.xml"
    $XPath = "/ns:catalog/ns:product[@product-id='50610']"

    $files = Get-ChildItem $Path | Where {-not $_.PSIsContainer}

    if ($files -eq $null) {
    return
    }

    foreach ($file in $files) {
    [xml]$xml = Get-Content $file
    $namespace = $xml.DocumentElement.NamespaceURI
    $ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
    $ns.AddNamespace("ns", $namespace)
    $product = $xml.SelectSingleNode($XPath, $ns)
    }

    几个问题:
  • 使用此代码,我可以选择所需的产品节点。 PowerShell 显示:
    online-flag        : {true, online-flag, online-flag, online-flag...}

    但是我如何才能选择所需的值 online-flag元素(如果两种方式都可能:XPath 一种和对象一种)?
  • 是否可以以“对象”方式选择节点?像这样:
    $product = $xml.catalog.product |
    Where-Object {$_."product-id".value -eq "50610"}
  • 如果我有多个文件,选择文件名、全局在线标志(无属性)、特定在线标志的最佳方法是什么?
  • 最佳答案

    使用两种不同的 XPath 表达式:

  • 用于选择没有特定属性的节点:

    //ns:product[@product-id='50610']/ns:online-flag[not(@site-id)]
  • 用于选择具有特定属性值的节点:

    //ns:product[@product-id='50610']/ns:online-flag[@site-id='ru']

  • 您可以通过使 XPath 表达式相对于当前节点 ( . ) 来选择相对于已选择节点的节点:

    $XPath = "/ns:catalog/ns:product[@product-id='50610']"
    ...
    $product = $xml.SelectSingleNode($XPath, $ns)
    $product.SelectSingleNode("./ns:online-flag[not(@site-id)]", $ns)
    $product.SelectSingleNode("./ns:online-flag[@site-id='ru']", $ns)

    如果您需要由文件名和两个节点值组成的结果数据,我建议您构建自定义对象:

    $files | ForEach-Object {
    [xml]$xml = Get-Content $_
    ...
    New-Object -Type PSObject -Property @{
    'Filename' = $_
    'online' = $product.SelectSingleNode("./ns:online-flag[not(@site-id)]", $ns).'#text'
    'ru_online' = $product.SelectSingleNode("./ns:online-flag[@site-id='ru']", $ns).'#text'
    }
    }

    通过 Where-Object 使用点符号和过滤应该是可能的,但我不会推荐它。我发现 XPath 效率更高。

    关于xml - 使用 PowerShell 解析带有命名空间的 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45676709/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com