【问题标题】:XML 'name' attribute, and XML variable type with SelectNodesXML 'name' 属性和带有 SelectNodes 的 XML 变量类型
【发布时间】:2019-08-16 18:30:23
【问题描述】:

我有两个关于 XML 的问题...

  1. 给定一个这样的 XML 节点

    <Product name="Dave">
    

    并分配给带有SelectSingleNode 的变量,$xmlNode.name 将返回 Dave。但是,如果 XML 是

    <Product id="Dave">
    

    然后$xmlNode.name 将返回产品。

    由于“name”可以引用节点的属性,也可以引用节点本身的名称,这是否完全反对使用 Name 作为属性,最佳实践是在这里使用 ID 之类的东西?或者这真的不太可能是一个问题吗,m,如果名称更有意义,然后运行它?

  2. 给定一堆 Product 节点,以及这样的代码

    $tempProducts = $temp.xml.SelectNodes('//Product')
    

    Write-Host "$($tempProducts.GetType())" 会提示结果变量的类型是

    System.Xml.XPathNodeList,System.Xml,版本=4.0.0.0, 文化=中立,PublicKeyToken=b77a5c561934e089

    然而,[System.Xml.XPathNodeList]$tempProducts = $temp.xml.SelectNodes('//Product') 会抛出一个错误,

    找不到类型 [System.Xml.XPathNodeList]。

这是因为我一直在一个大型脚本中输入我的变量,并认为它可能会节省一些调试时间。但是这一个条件似乎给我带来了麻烦。

有什么想法吗?

【问题讨论】:

  • 如果您使用 XPath 来选择您的属性,那么您可以始终使用.Name 进行属性名称检索,并使用.Value 来检索这些属性的文本值。如果您使用SelectNodes(),它将输出XmlNodeList 类型。为什么要把它转换成别的东西?
  • 关于类型,我并没有尝试强制转换,我只是想故意用我会得到的类型输入变量。所以我使用 getType() 来确定我需要使用什么。似乎 GetType 是……错了?
  • 我想我没有给你一个明确的答案。 $temp.xml.SelectNodes('//Product') -is [System.Xml.XmlNodeList] 仍然返回 true,因为这是它的基本类型。

标签: xml powershell xpath


【解决方案1】:

回复 1:

PowerShelladapts XML 元素为方便起见,通过将它们的子节点及其属性显示为常规 对象属性

这通常使得在 PowerShell 中使用 XML 非常方便,但也有缺陷:

如果与基础System.Xml.XmlElement 类型的属性存在命名冲突,则已调整 属性优先。

这发生在您的示例 XML 中的 Name 属性 上:PowerShell 将其公开为 .Name 属性,它隐藏 XMlElement.Name 属性报告标签名称

一个简单的解决方法是调用属性访问器方法.get_Name() 来获取阴影XmlElement 属性:

$node = ([xml] '<xml><Product Name="Dave" /></xml>').SelectSingleNode('//Product')

$node.Name       # adapted property: Name *attribute* -> 'Dave'
$node.get_Name() # native property: tag name -> 'Product'

也就是说,如果您控制 XML 的格式,最好从一开始就避免这样的冲突。


回复 2:

.SelectNodes() 可能会令人惊讶地返回一个类型,该类型派生自记录在案的 System.Xml.XmlNodeList 返回类型,并且该派生类型本身不公开System.Xml.XPathNodeList is internal

这在实践中不是问题,因为重要的是它可以充当System.Xml.XmlNodeList 实例,但可能会令人困惑。

给定一个类型的实例,您可以检查该类型的派生(基类链),如下所示:

$nodeList = ([xml] '<xml><Product Name="Dave" /><Product Name="Jane" /></xml>').SelectNodes('//Product')

$type = $nodeList.GetType()
do {
 $type.FullName 
} while ($type = $type.BaseType)

以上产出:

System.Xml.XPathNodeList
System.Xml.XmlNodeList
System.Object

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多