如何使用 PowerShell 从 XML 中提取 ErrorCode 和 ErrorDescription?

How do I extract using PowerShell the ErrorCode & ErrorDescription from this XML?

我在尝试从以下 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

我猜想取值难的原因是这里使用的命名空间(几个) 预先感谢所有帮助。

你照着做就行了:

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>
'@

$errorCode = $res.Envelope.Body.ActionResponse.ActionResult.ErrorCode
$ErrorDescription = $res.Envelope.Body.ActionResponse.ActionResult.ErrorDescription

如果您可以使用此代码获得更多 ActionResponses:

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>
      <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>2</a:ErrorCode>
            <a:ErrorDescription>General2 Error</a:ErrorDescription>
         </ActionResult>
      </ActionResponse>
   </s:Body>
</s:Envelope>
'@

$actResponses = $res.Envelope.Body.ChildNodes
foreach($act in $actResponses){
 "Error code :" + $act.ActionResult.ErrorCode + " Description: " + $act.ActionResult.ErrorDescription
}

如果您不关心名称空间或不使用 XPATH,则可以使用


如果您不关心名称空间但必须使用 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

此处您有一个未指定名称的命名空间定义。由于我们使用散列 table 来管理名称空间,因此最好在散列 table 中给它一个 name/key。然后,您可以在 XPATH 表达式中引用散列 table 键名。

您可以将 XPATH 改为 select ActionResult 节点。然后使用另一个具有不同 XPATH 的 Select-Xml 到 select 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