我有下面的 xml 文件,有 id 和 value 。需要 ID 为 3 的 field_name =test2 的结果
<Types>
<Type field_name="Test1">
<items>
<item>
<id>1</id>
<value>A</value>
</item>
<item>
<id>2</id>
<value>B</value>
</item>
<item>
<id>3</id>
<value>C</value>
</item>
<item>
<id>4</id>
<value>D</value>
</item>
</items>
</Type>
<Type field_name="Test2">
<items>
<item>
<id>1</id>
<value>A</value>
</item>
<item>
<id>2</id>
<value>B</value>
</item>
<item>
<id>3</id>
<value>C</value>
</item>
<item>
<id>4</id>
<value>D</value>
</item>
</items>
</Type>
</Types>
Run Code Online (Sandbox Code Playgroud)
我需要通过id和 field_name =test2 获取结果,我尝试过下面的代码,但没有成功。
$xml = [xml](Get-Content "C:\Test.xml")
$xml.types.type.items.item | ? {$_.id -eq 3} | select value
Run Code Online (Sandbox Code Playgroud)
# This is a more robust way to load an XML file (PSv5+).
# In earlier versions, use ($xml = New-Object xml)...
($xml = [xml]::new()).Load((Convert-Path C:\Test.xml))
# PSv4+ syntax
@($xml.types.type.Where({ $_.'field_name' -eq 'Test2' }, 'First').
items).ForEach({ $_.item }).Where({ $_.id -eq 3 }).value
Run Code Online (Sandbox Code Playgroud)
请注意使用 PSv4+.Where()和.ForEach()数组方法进行过滤和枚举,特别是需要显式枚举子<item>元素.ForEach()(请参阅底部部分)。
注意:严格来说,由于.Where()调用仅返回一个只有一个子元素的对象, items因此在这种.ForEach()情况下并不是严格必需的,但在原始代码中却是必需的。
另请注意 的使用,仅在Windows PowerShell中才需要,因为该错误已在PowerShell (Core) 7+中修复@(...)
但是,使用XPath查询更容易,它与 结合使用Select-Xml,可以实现单命令解决方案:
(Select-Xml '//Type[@field_name="Test2"]/items/item[id=3]' C:\Test.xml).Node.value
Run Code Online (Sandbox Code Playgroud)
笔记:
如果您的 XML 文档使用命名空间,则必须将带有前缀到 URI 映射的哈希表传递给参数-Namespace,并在引用元素时在查询中使用这些前缀 - 请参阅此答案以获取更多信息。
相比之下,如果您使用 PowerShell 的 XML DOM 适配(基于属性的访问),则元素名称中的命名空间声明和命名空间前缀将被忽略。
至于你尝试过的:
除了您的代码不尝试进行过滤field_name="Test2"(如果值在整个文档中是唯一的,则可能没有必要)之外,您的问题是在array值父属性上id使用该属性, :.item.items
因为.items是一个数组,并且数组有一个类型本机 .Item成员[1],所以该成员优先于PowerShell 对 XML DOM 的改编(其中属性和子元素显示为属性),因此命名的子 XML 元素item不是可以直接通过 访问更长的时间.item。
数组元素(在本例中为 XML 元素)的显式枚举 - 通过.ForEach({ $_.item })[2] - 绕过了问题,然后访问.item每个元素的属性[XmlElement]即可按预期工作。
注意:XmlElements也有一个类型本机.Item属性,但是在 PowerShell 对 XML DOM 的适应的上下文中,逻辑是相反的:适应的属性优先于类型本机属性(后者可以作为带有get_前缀;例如.get_Item()) - 请参阅此答案以获取一个示例,该示例具有调整后的.Name属性(来自子元素或属性),该属性遮蔽了元素的类型本机属性。
[1] 从技术上讲,参数化.Item属性是通过接口( IList) 公开的,但 PowerShell 将此类显式接口实现属性视为类型的直接属性。
[2] 理想情况下,您可以将其用作更快的替代方案,但从 PowerShell (Core) 7.2 开始,由于存在bug.ForEach('item') ,该方法无法正常工作,详细信息请参阅GitHub 问题 #15994。
| 归档时间: |
|
| 查看次数: |
456 次 |
| 最近记录: |