我正在尝试从XML文件中选择节点,但是遇到的问题似乎是由名称空间引起的。
下面的代码不返回任何内容。但是,如果我从XML文件中删除名称空间,则会得到预期的结果。
$StandaloneXML = "test.xml"
# Load XML content
$NewStandaloneXML = New-Object -TypeName "System.XML.XMLDocument"
$NewStandaloneXML.Load($StandaloneXML)
# Get namespace
$Namespace = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $NewStandaloneXML.NameTable
$Namespace.AddNamespace("jboss", $NewStandaloneXML.DocumentElement.NamespaceURI)
$NewStandaloneXML.SelectNodes("jboss:server/interfaces/interface", $Namespace)
<?xml version="1.0" ?>
<server xmlns="urn:jboss:domain:4.2">
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
</server>
name inet-address ---- ------------ management inet-address public inet-address
答案 0 :(得分:2)
正如@AnsgarWiechers所说,每个节点都必须以其命名空间作为前缀,因为没有继承。
$StandaloneXML = "test.xml"
# Load XML content
$NewStandaloneXML = New-Object -TypeName "System.XML.XMLDocument"
$NewStandaloneXML.Load($StandaloneXML)
# Get namespace
$Namespace = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $NewStandaloneXML.NameTable
$Namespace.AddNamespace("jboss", $NewStandaloneXML.DocumentElement.NamespaceURI)
$NewStandaloneXML.SelectNodes("jboss:server/jboss:interfaces/jboss:interface", $Namespace)
为了使事情变得容易,我构建了一个小函数来自动为提供的XPath
中的每个节点加上前缀。
function Select-XMLNode {
[CmdletBinding()]
Param (
[Parameter (
Position = 1,
Mandatory = $true,
HelpMessage = "XML content"
)]
[ValidateNotNullOrEmpty()]
[System.XML.XMLDocument]
$XML,
[Parameter (
Position = 2,
Mandatory = $true,
HelpMessage = "XPath corresponding to the node"
)]
[ValidateNotNullOrEmpty()]
[String]
$XPath,
[Parameter (
Position = 3,
Mandatory = $false,
HelpMessage = "Namespace"
)]
[ValidateNotNullOrEmpty()]
[String]
$Namespace = $XML.DocumentElement.NamespaceURI
)
Begin {
# Variables
$Delimiter = "/"
$Alias = "x"
$SpecialCharacters = [RegEx]::New('^[/.@]*')
if ($XPath -match $SpecialCharacters) {
$Prefix = $Matches[0]
$XPath = $XPath -replace $SpecialCharacters, ''
}
}
Process {
# Get namespace
$NamespaceManager = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $XML.NameTable
$NamespaceManager.AddNamespace($Alias, $Namespace)
# Split XPath to identify nodes
$Nodes = $XPath.Split($Delimiter)
$PrefixedNodes = New-Object -TypeName "System.Collections.ArrayList"
# Prefix nodes with namespace (alias)
foreach($Node in $Nodes) {
if ($Node) {
[Void]$PrefixedNodes.Add("${Alias}:${Node}")
}
}
# Join prefixed-nodes to create new XPath with namespace
$XPathWithNamespace = $PrefixedNodes -join $Delimiter
# Check XPath prefix
if ($Prefix) {
$XPathWithNamespace = $Prefix + "" + $XPathWithNamespace
}
# Select and return nodes
$SelectedNodes = $XML.SelectNodes($XPathWithNamespace, $NamespaceManager)
return $SelectedNodes
}
}