在PowerShell对象中访问XML数据

8aqjt8rx  于 2023-06-29  发布在  Shell
关注(0)|答案(3)|浏览(132)

我正在尝试从XML中读取数据到PowerShell中。

<?xml version="1.0" encoding="UTF-8"?>

<?xml-stylesheet type="text/xsl" href="tmp.xslt"?>
<Book>
   <Subbook id="1848">
        <variable Name="Metadata_Code" Value="A-"/>
        <variable Name="Metadata_Installation" Value="pod - A"/>
        <Topic...>
        <Topic....>
   </Subbook>
    <Subbook id="1849">
        <variable Name="Metadata_Code" Value="B-"/>
        <variable Name="Metadata_Installation" Value="pod - B"/>
        <Topic...>
        <Topic....>
    </Subbook>
</Book>

我想循环所有Subbook元素。每个Subbook元素都包含一些可变元素。此外,它还包含了我必须处理的其他元素。我可以设置循环。

[xml]$xmlfile = Get-Content -Path $xmlpath
$subbooks = Select-Xml -Path $xmlpath -XPath '//Subbook'
$subbooks | ForEach-Object {
    $MDC = $_.Node.SelectNodes('variable[@Name="Metadata_Code"]/@Value')
}

但我被困住了。我需要选择名为“Metadata_Code”的变量节点的值。在XSLT中,这是变量[@Name ='Metadata_Code']/@Value
$MDC仍为空。我怎样才能得到我需要的值到这个变量?

twh00eeo

twh00eeo1#

假设您在示例XML中查找的是A-B-,如果您希望使用PowerShell执行过滤,则代码如下所示:

($xmlfile = [xml]::new()).Load($xmlpath)
$xmlfile.Book.Subbook.variable |
    Where-Object Name -EQ 'Metadata_Code' |
    ForEach-Object Value
atmip9wb

atmip9wb2#

Santiago's helpful answer向您展示了如何使用PowerShell's dot-notation-based adaptation of the [xml] DOM解决问题。
至于您的基于XPath的尝试:

  • 更新 ,基于your own answer
    tl;dr您的代码 * 工作正常
    ,但显示错误使您无法意识到这一点。详情如下。
    ***$MDC实际上并不是 * 空 *,但是您尝试 * 可视化 * 它包含的System.Xml.XmlNodeList示例(由.SelectNodes()返回)的方式,即通过Write-Host导致 * 没有显示输出 *。
  • 虽然这应该被认为是一个 bug -参见GitHub issue #19769-但使用Write-Host来显示 * 复杂对象 * 很少有帮助。
  • 事实上,Write-Host is typically the wrong tool to use,除非意图是只写 * 到显示 *,绕过成功输出流,并能够将输出发送到其他命令,将其捕获在变量中,或将其重定向到文件。要输出一个值,请使用它 * 本身 *;例如,$MDC,而不是Write-Host $MDC(或使用Write-Output $MDC);参见this answer。要显式地只打印到显示器 * 但使用丰富格式 *,请使用Out-Host
  • 此外,如下面的代码所示,您需要访问$MDC中示例System.Xml.XmlAttribute.Value属性,以便仅获取属性的 value(文本)。
  • 顺便说一句:如果您正在使用 *identifying属性 * 查找 * 单个 * 节点,请使用.SelectSingleNode()而不是.SelectNodes()

除此之外,您的代码可以简化。下面是一个包含示例XML的自包含示例:

# Create sample XML file
@'
<?xml version="1.0" encoding="UTF-8"?>

<?xml-stylesheet type="text/xsl" href="tmp.xslt"?>
<Book>
<Subbook id="1848">
<variable Name="Metadata_Code" Value="A-"/>
<variable Name="Metadata_Installation" Value="pod - A"/>
</Subbook>
<Subbook id="1849">
<variable Name="Metadata_Code" Value="B-"/>
<variable Name="Metadata_Installation" Value="pod - B"/>
</Subbook>
</Book>
'@ > file.xml

# Let Select-Xml parse the file directly
# and use a single XPath query to extract the target nodes.
Get-Item file.xml | 
  Select-Xml '//Subbook/variable[@Name="Metadata_Code"]/@Value' | 
  ForEach-Object { $_.Node.Value }

输出(在上面的管道前添加类似$MDC =的内容,以在变量中捕获输出字符串):

A-
B-
bfrts1fy

bfrts1fy3#

问题是

$MDC = $_.Node.SelectNodes('variable[@Name="Metadata_Code"]/@Value')

输出节点集。我使用Write-Host $MDC来查看内容,当变量content是一个节点集时,它不显示任何内容。
这就是我一直在寻找的价值:

$MDC = $_.Node.SelectNodes('variable[@Name="Metadata_Code"]/@Value').Value

相关问题