如何使用powershell多次从xml文档中进行选择

时间:2022-06-24 07:15:12

I am trying to select multiple groups of elements from an XML document, the sample below shows the type of structure I'm using. Why does the powershell code below only output the 2 names, but not the 2 stores.

我试图从XML文档中选择多组元素,下面的示例显示了我正在使用的结构类型。为什么下面的powershell代码只输出2个名称,而不是2个商店。

[xml]$xml = @'
<root>
  <node>
    <store>HEB</store>
    <name>Fred</name>
  </node>
  <node>
    <store>Fred Meyer</store>
    <name>Barney</name>
  </node>
</root>
'@;

$xml.root.node | select  name -unique

$xml.root.node | select store -unique

Output

.\test.ps1

name
----
Fred
Barney

Desired Output

.\test.ps1

name
----
Fred
Barney

store
-----
HEB
Fred Meyer

1 个解决方案

#1


0  

Try this code:

试试这段代码:

[xml]$xml = @'
<root>
  <node>
    <store>HEB</store>
    <name>Fred</name>
  </node>
  <node>
    <store>Fred Meyer</store>
    <name>Barney</name>
  </node>
</root>
'@;

$xml.root.node | select name  -unique | Out-String

$xml.root.node | select store -unique | Out-String

The issue appears to be only when you run the code from a script (.ps1). When you run the raw code from the prompt, it works perfectly.

只有从脚本(.ps1)运行代码时才会出现此问题。当您从提示符运行原始代码时,它完美地运行。

The issue that you are encountering is how PowerShell returns the output from a script. Whenever possible it will try to return the full object rather than finally defaulting to a base string object.

您遇到的问题是PowerShell如何从脚本返回输出。只要有可能,它将尝试返回完整对象,而不是最终默认为基本字符串对象。

So lets step through this:

所以让我们一步一步:

Original code:

$xml.root.node | select  name -unique
$xml.root.node | select store -unique

PS C:\> $a = .\Test.ps1
PS C:\> $a

name
----
Fred
Barney



PS C:\> $a | Get-Member


   TypeName: Selected.System.Xml.XmlElement

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
name        NoteProperty System.String name=Fred

Notice that the TypeName is a XmlElement, and based on the members, there is a NoteProperty "name".

请注意,TypeName是一个XmlElement,并且基于成员,有一个NoteProperty“name”。

When we flip the code around:

当我们翻转代码时:

$xml.root.node | select store -unique
$xml.root.node | select  name -unique

PS C:\> $b = .\Test.ps1
PS C:\> $b

store
-----
HEB
Fred Meyer




PS C:\> $b | Get-Member


   TypeName: Selected.System.Xml.XmlElement

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
store       NoteProperty System.String store=HEB

Notice that the TypeName is a XmlElement, and there is a NoteProperty "store".

请注意,TypeName是一个XmlElement,并且有一个NoteProperty“store”。

Basically what is happening is that once PowerShell hits the first command it sets the "Output" variable type to the first element, i.e. name. When it hits the second element, it tries to shove the contents into the predefined output type, and fills it with nothing (because there is no name field). You can verify this by getting the count:

基本上发生的事情是,一旦PowerShell命中第一个命令,它就将“输出”变量类型设置为第一个元素,即名称。当它命中第二个元素时,它会尝试将内容推送到预定义的输出类型中,并且没有任何内容填充它(因为没有名称字段)。您可以通过获取计数来验证这一点:

PS C:\> $a.Count
4

So there are 4 elements, but only the first two actually contain information that we want.

所以有4个元素,但只有前两个实际包含我们想要的信息。

The workaround is to output both elements as a string so that the Output type is a string, then it will return both values.

解决方法是将两个元素作为字符串输出,以便Output类型为字符串,然后它将返回两个值。

PS C:\> $c = .\Test.ps1
PS C:\> $c

name
----
Fred
Barney




store
-----
HEB
Fred Meyer

#1


0  

Try this code:

试试这段代码:

[xml]$xml = @'
<root>
  <node>
    <store>HEB</store>
    <name>Fred</name>
  </node>
  <node>
    <store>Fred Meyer</store>
    <name>Barney</name>
  </node>
</root>
'@;

$xml.root.node | select name  -unique | Out-String

$xml.root.node | select store -unique | Out-String

The issue appears to be only when you run the code from a script (.ps1). When you run the raw code from the prompt, it works perfectly.

只有从脚本(.ps1)运行代码时才会出现此问题。当您从提示符运行原始代码时,它完美地运行。

The issue that you are encountering is how PowerShell returns the output from a script. Whenever possible it will try to return the full object rather than finally defaulting to a base string object.

您遇到的问题是PowerShell如何从脚本返回输出。只要有可能,它将尝试返回完整对象,而不是最终默认为基本字符串对象。

So lets step through this:

所以让我们一步一步:

Original code:

$xml.root.node | select  name -unique
$xml.root.node | select store -unique

PS C:\> $a = .\Test.ps1
PS C:\> $a

name
----
Fred
Barney



PS C:\> $a | Get-Member


   TypeName: Selected.System.Xml.XmlElement

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
name        NoteProperty System.String name=Fred

Notice that the TypeName is a XmlElement, and based on the members, there is a NoteProperty "name".

请注意,TypeName是一个XmlElement,并且基于成员,有一个NoteProperty“name”。

When we flip the code around:

当我们翻转代码时:

$xml.root.node | select store -unique
$xml.root.node | select  name -unique

PS C:\> $b = .\Test.ps1
PS C:\> $b

store
-----
HEB
Fred Meyer




PS C:\> $b | Get-Member


   TypeName: Selected.System.Xml.XmlElement

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
store       NoteProperty System.String store=HEB

Notice that the TypeName is a XmlElement, and there is a NoteProperty "store".

请注意,TypeName是一个XmlElement,并且有一个NoteProperty“store”。

Basically what is happening is that once PowerShell hits the first command it sets the "Output" variable type to the first element, i.e. name. When it hits the second element, it tries to shove the contents into the predefined output type, and fills it with nothing (because there is no name field). You can verify this by getting the count:

基本上发生的事情是,一旦PowerShell命中第一个命令,它就将“输出”变量类型设置为第一个元素,即名称。当它命中第二个元素时,它会尝试将内容推送到预定义的输出类型中,并且没有任何内容填充它(因为没有名称字段)。您可以通过获取计数来验证这一点:

PS C:\> $a.Count
4

So there are 4 elements, but only the first two actually contain information that we want.

所以有4个元素,但只有前两个实际包含我们想要的信息。

The workaround is to output both elements as a string so that the Output type is a string, then it will return both values.

解决方法是将两个元素作为字符串输出,以便Output类型为字符串,然后它将返回两个值。

PS C:\> $c = .\Test.ps1
PS C:\> $c

name
----
Fred
Barney




store
-----
HEB
Fred Meyer