首页 > 解决方案 > 如何使用 PowerShell 从此 XML 中提取 ErrorCode 和 ErrorDescription?

问题描述

我在尝试从以下 XML 中获取 ErrorCode 和 ErrorDescription 的值时遇到了很多困难:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <ActionResponse xmlns="http://tempuri.org/">
         <ActionResult xmlns:a="http://schemas.datacontract.org/2004/07/RL.Common.CommonTypes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:ErrorCode>1</a:ErrorCode>
            <a:ErrorDescription>General Error</a:ErrorDescription>
         </ActionResult>
      </ActionResponse>
   </s:Body>
</s:Envelope>

尝试了以下方法,它正在工作,但在我看来,这种工作方式很糟糕:

cls

$res = [xml]@'
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <ActionResponse xmlns="http://tempuri.org/">
         <ActionResult xmlns:a="http://schemas.datacontract.org/2004/07/RL.Common.CommonTypes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:ErrorCode>1</a:ErrorCode>
            <a:ErrorDescription>General Error</a:ErrorDescription>
         </ActionResult>
      </ActionResponse>
   </s:Body>
</s:Envelope>
'@


$XPath = "/ns:Envelope/ns:Body"

[xml]$xml = $res
$namespace = $xml.DocumentElement.NamespaceURI
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace("ns", $namespace)
$ns.AddNamespace("nsa", "http://tempuri.org/")
$ns.AddNamespace("nsb", "http://tempuri.org/")
$product = $xml.SelectSingleNode($XPath, $ns)

Write-Host $product

#exit


$XPath = "/ns:Envelope/ns:Body"


[xml]$xml = $res
$namespace = $xml.DocumentElement.NamespaceURI
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace("ns", $namespace)
$product = $xml.SelectSingleNode($XPath, $ns)
#Write-Host $product.InnerXml


#$newres = [xml]@'
#<ActionResponse xmlns="http://tempuri.org/"><ActionResult xmlns:a="http://schemas.datacontract.org/2004/07/RL.Common.CommonTypes" xmlns:i="http://www.w3.org/2001/XMLS
#chema-instance"><a:ErrorCode>1</a:ErrorCode><a:ErrorDescription>General Error</a:ErrorDescription></ActionResult></ActionResponse>
#'@

[xml]$newres = $product.InnerXml

$XPath = "/ns:ActionResponse"

[xml]$xml = $newres
$namespace = $xml.DocumentElement.NamespaceURI
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace("ns", $namespace)
$product = $xml.SelectSingleNode($XPath, $ns)


$XPath = "/ns:ActionResult" 

[xml]$xml = $product.InnerXml
$namespace = $xml.DocumentElement.NamespaceURI
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace("ns", $namespace)
$product = $xml.SelectSingleNode($XPath, $ns)

Write-Host "ErrCode: ",$product.ErrorCode ," ErrDesc: ",$product.ErrorDescription
Write-Host $product.ErrorCode, $product.ErrorDescription

我想难以获得值的原因是由于这里使用的名称空间(几个)提前感谢所有帮助。

标签: xmlpowershellnamespaces

解决方案


如果您不关心命名空间或使用 XPATH,您可以使用Frenchy's Answer 。


如果您不关心命名空间但必须使用 XPATH,您可以使用该local-name()功能。

$res = [xml]@'
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <ActionResponse xmlns="http://tempuri.org/">
         <ActionResult xmlns:a="http://schemas.datacontract.org/2004/07/RL.Common.CommonTypes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:ErrorCode>1</a:ErrorCode>
            <a:ErrorDescription>General Error</a:ErrorDescription>
         </ActionResult>
      </ActionResponse>
   </s:Body>
</s:Envelope>
'@

$XPath = '//*[local-name() = "ErrorCode" or local-name() = "ErrorDescription"]'

$Nodes = (Select-Xml -Xml $res -XPath $XPath).Node
$Nodes # Your Xml elements

如果要使用定义的命名空间和 XPATH,可以执行以下操作:

$res = [xml]@'
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <ActionResponse xmlns="http://tempuri.org/">
         <ActionResult xmlns:a="http://schemas.datacontract.org/2004/07/RL.Common.CommonTypes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:ErrorCode>1</a:ErrorCode>
            <a:ErrorDescription>General Error</a:ErrorDescription>
         </ActionResult>
      </ActionResponse>
   </s:Body>
</s:Envelope>
'@
$XPath = '/s:Envelope/s:Body/NSWithNoName:ActionResponse/NSWithNoName:ActionResult/a:*["ErrorCode" or "ErrorDescription"]'

$ns = @{ a = 'http://schemas.datacontract.org/2004/07/RL.Common.CommonTypes'
         s = "http://schemas.xmlsoap.org/soap/envelope/"                                                                                                                                   
         NSWithNoName = "http://tempuri.org/"
}

$Nodes = (Select-Xml -Xml $res -XPath $XPath -Namespace $ns).Node
$Nodes # Your xml elements ErrorCode and ErrorDescription

在这里,您有一个没有指定名称的命名空间定义。由于我们使用哈希表来管理命名空间,因此最好在该哈希表中给它一个名称/键。然后,您可以在 XPATH 表达式中引用哈希表键名。

您可以修改 XPATH 以改为选择ActionResult节点。然后使用另一个Select-Xml具有不同 XPATH 的来选择ErrorCodeErrorDescription节点。

$XPath = '/s:Envelope/s:Body/NSWithNoName:ActionResponse/NSWithNoName:ActionResult'

$ARNode = (Select-Xml -Xml $res -XPath $XPath -Namespace $ns).Node
$ECNode = (Select-Xml -Xml $ARNode -XPath './a:ErrorCode' -Namespace $ns).Node
$EDNode = (Select-Xml -Xml $ARNode -XPath './a:ErrorDescription' -Namespace $ns).Node

推荐阅读