【发布时间】:2013-07-04 02:44:00
【问题描述】:
我正在使用 PowerShell v3 和 Windows PowerShell ISE。我有以下功能可以正常工作:
function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
# If a Namespace URI was not given, use the Xml document's default namespace.
if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }
# In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
[System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter
# Try and get the node, then return it. Returns $null if the node was not found.
$node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}
现在,我将创建一些类似的函数,所以我想将前 3 行拆分成一个新函数,这样我就不必到处复制粘贴了,所以我这样做了:
function Get-XmlNamespaceManager([xml]$XmlDocument, [string]$NamespaceURI = "")
{
# If a Namespace URI was not given, use the Xml document's default namespace.
if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }
# In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
[System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
return $xmlNsManager
}
function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
[System.Xml.XmlNamespaceManager]$xmlNsManager = Get-XmlNamespaceManager -XmlDocument $XmlDocument -NamespaceURI $NamespaceURI
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter
# Try and get the node, then return it. Returns $null if the node was not found.
$node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}
问题是当“return $xmlNsManager”执行时抛出如下错误:
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Xml.XmlNamespaceManager".
因此,即使我已将 $xmlNsManager 变量显式转换为 System.Xml.XmlNamespaceManager 类型,当它从 Get-XmlNamespaceManager 函数返回时,PowerShell 也会将其转换为对象数组。
如果我没有将 Get-XmlNamespaceManager 函数返回的值显式转换为 System.Xml.XmlNamespaceManager,则 .SelectSingleNode() 函数会引发以下错误,因为将错误的数据类型传递到函数的第二个参数。
Cannot find an overload for "SelectSingleNode" and the argument count: "2".
因此,出于某种原因,PowerShell 没有维护返回变量的数据类型。我真的很想从一个函数中得到这个工作,这样我就不必到处复制粘贴这 3 行了。任何建议表示赞赏。谢谢。
【问题讨论】:
-
那么您对内置的
Select-Xmlcmdlet 有什么看法?使用命名空间就像将前缀哈希表传递给命名空间映射一样简单,例如$xml | Select-Xml -XPath '//dns:foo' -namespace @{dns='http://schema.foo.org'} -
感谢 Keith,我实际上没有听说过 Select-Xml cmdlet。我宁愿忽略 Xml 命名空间,因为我不关心它,但不幸的是 .SelectSingleNode() 需要它,正如我在我的博客文章 (blog.danskingdom.com/…) 中讨论的那样。使用 Select-Xml 会解决这个问题吗?
-
Select-Xml只是在幕后调用SelectSingleNode或SelectNodes(来自XmlDocument),因此它仍然容易受到XML 命名空间的影响,这就是@Keith 使用-namespace参数的原因。跨度> -
顺便说一句,有一种方法可以完全忽略 XML 命名空间,您只需要以不同的方式编写 Xpath。 This SO question 展示了如何。
标签: function powershell powershell-3.0 return-type powershell-ise