访问 Powershell 对象中的 XML 数据

huangapple go评论56阅读模式
英文:

Access XML data within a Powershell object

问题

我正在尝试从XML中读取数据到Powershell中。我想循环遍历所有Subbook元素。每个Subbook元素都包含一些variable元素,此外还包含其他我需要处理的元素。我可以设置循环。

[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'的variable节点的值。在XSLT中,这是variable[@Name='Metadata_Code']/@Value。

$MDC保持为空。我如何将我需要的值放入这个变量中?

英文:

I'm trying to read data from an XML into 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>

I want to loop through all Subbook elements. Each Subbook element contains a few variable elements. In addition it contains other elements I have to process.
I can set up the loop.

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

But then I'm stuck. I need to select the value of the variable node that has name 'Metadata_Code'. In XSLT this is variable[@Name='Metadata_Code']/@Value

$MDC remains empty. How can I get the value I need into this variable?

答案1

得分: 1

假设你在示例XML中正在寻找的是A-B-,如果你想要使用PowerShell来执行筛选,代码将如下所示:

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

Assuming what you're looking for in your example XML is A- and B-, if you want to use PowerShell to perform the filtering, the code would look like this:

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

答案2

得分: 1

[Santiago的有益答案](https://stackoverflow.com/a/76432968/45375)向你展示了如何使用PowerShell的点符号适配`[xml]` DOM来解决你的问题。

至于你基于XPath的尝试:

根据[你自己的答案](https://stackoverflow.com/a/76433080/45375)进行了更新:

**简而言之**:**你的代码是有效的**,但一个**显示错误**阻止了你意识到这一点。详情如下。

- `$MDC`实际上**并不是空的**,但是你试图通过[`System.Xml.XmlNodeList`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlNodeList)实例来进行可视化(由[`.SelectNodes()`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlDocument.SelectNodes)返回),也就是通过[`Write-Host`](https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Write-Host),结果是**没有显示输出**。

  - 虽然这应该被视为一个**错误** - 请参见[GitHub问题#19769](https://github.com/PowerShell/PowerShell/issues/19769) - 但使用`Write-Host`来显示**复杂对象**通常是没有帮助的。

  - 实际上,[通常使用`Write-Host`是错误的工具](http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/),除非意图是仅仅写入**显示**,绕过成功输出流,以及将输出发送到其他命令,将其捕获到一个变量中,或者将其重定向到文件中的能力。要输出一个值,请使用它**单独**,例如`$MDC`,而不是`Write-Host $MDC`(或使用`Write-Output $MDC`);参见[这个答案](https://stackoverflow.com/a/60534138/45375)。要明确地仅仅打印到显示器**但具有丰富的格式**,请使用[`Out-Host`](https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Core/Out-Host)。

- 此外 - 正如下面的代码中也显示的那样 - 你需要访问`$MDC`中`System.Xml.XmlAttribute`实例的`.Value`属性,以便只获取属性的**值**(文本)。

- 顺便说一句:如果你只是使用一个**标识属性**来查找**单个节点**,请使用[`.SelectSingleNode()`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlDocument.SelectSingleNode)而不是`.SelectNodes()`

除此之外,你的代码可以**简化**。以下是一个包含你的样本XML的独立示例:

```powershell
# 创建样本XML文件
@'
<?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

# 让Select-Xml直接解析文件,并使用单个XPath查询提取目标节点。
Get-Item file.xml | 
  Select-Xml '//Subbook/variable[@Name="Metadata_Code"]/@Value' | 
  ForEach-Object { $_.Node.Value }

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

A-
B-

<details>
<summary>英文:</summary>

&lt;!-- language-all: sh --&gt;

[Santiago&#39;s helpful answer](https://stackoverflow.com/a/76432968/45375) shows you how to solve your problem using [PowerShell&#39;s dot-notation-based adaptation of the `[xml]` DOM](https://stackoverflow.com/a/49213568/45375).

As for your **XPath-based** attempt:

_Update_, based on [your own answer](https://stackoverflow.com/a/76433080/45375):

**tl;dr**: **Your code *works***, but a **display bug** prevented you from realizing that. Details below.


* **`$MDC` wasn&#39;t actually _empty_**, but the way you tried to _visualize_ the [`System.Xml.XmlNodeList`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlNodeList) instance it contained (returned by [`.SelectNodes()`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlDocument.SelectNodes)), namely via [`Write-Host`](https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Write-Host) resulted in _no display output_.

  * While this should be considered a _bug_ - see [GitHub issue #19769](https://github.com/PowerShell/PowerShell/issues/19769) - it is rarely helpful to use `Write-Host` to display _complex objects_.

  * In fact, [`Write-Host` is typically the wrong tool to use](http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/), unless the intent is to write _to the display only_, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it _by itself_; e.g, `$MDC`, instead of `Write-Host $MDC` (or use `Write-Output $MDC`); see [this answer](https://stackoverflow.com/a/60534138/45375). To explicitly print only to the display _but with rich formatting_, use [`Out-Host`](https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Core/Out-Host).

* Additionally - as also shown in the code below - you needed to access the `.Value` property of the instance [`System.Xml.XmlAttribute`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlAttribute) in `$MDC` in order to get only the attribute&#39;s _value_ (text).

* As an aside: If you&#39;re looking for just a _single_ node using an _identifying attribute_, use [`.SelectSingleNode()`](https://learn.microsoft.com/en-US/dotnet/api/System.Xml.XmlDocument.SelectSingleNode) instead of `.SelectNodes()`


Aside from that, your **code can be simplified**.
Here&#39;s a self-contained example with your sample 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 }


Output (prepend something like `$MDC = ` to the pipeline above to capture the output strings in a variable):

```none
A-
B-

答案3

得分: 0

问题在于

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

输出一个节点集。我之前使用 Write-Host $MDC 来查看内容,但当变量内容是节点集时,这将显示为空。

这会给我所寻找的值:

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

The problem is that

$MDC = $_.Node.SelectNodes(&#39;variable[@Name=&quot;Metadata_Code&quot;]/@Value&#39;)

outputs a node-set.
I was using Write-Host $MDC to see the contents, this displays nothing when the variable content is a nodeset.

This gives me the value I was looking for:

$MDC = $_.Node.SelectNodes(&#39;variable[@Name=&quot;Metadata_Code&quot;]/@Value&#39;).Value

huangapple
  • 本文由 发表于 2023年6月8日 22:15:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76432787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定