【问题标题】:How do I extract using PowerShell the ErrorCode & ErrorDescription from this XML?如何使用 PowerShell 从此 XML 中提取 ErrorCode 和 ErrorDescription?
【发布时间】:2021-05-24 17:28:48
【问题描述】:

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

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

【问题讨论】:

  • 如果你想使用 XPATH 但忽略命名空间,那么你可以使用 XPATH local-name() 函数。 $XPath = '//*[local-name()="ActionResult"]'.
  • 我认为我不能忽略名称空间,因为这个 xnl 是运行 Web 服务的结果,除非我在这里遗漏了一些东西..

标签: xml powershell namespaces


【解决方案1】:

如果您不关心命名空间或使用 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 节点。然后使用另一个具有不同 XPATH 的 Select-Xml 来选择 ErrorCode 和 ErrorDescription 节点。

$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

【讨论】:

  • 这个解决方案看起来不错,我会尝试(但仅在下周)并会更新。非常感谢这个详细的答案
  • 嗨,很抱歉回复晚了,再次感谢这个详细的解决方案,尝试了第一个,它失败了,因为 $ns 没有定义,不知道如何定义它,但后来检查了第二个它就像魔术一样起作用,然后从第 2 次获取 $ns 的定义并将其放在第 1 次,它也使它起作用。最重要的是,您已经解决了它:),非常感谢!
【解决方案2】:

你只要跟着路就行了:

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
}

【讨论】:

  • 嗨,我已经尝试过这种方法,但它什么也没返回...
  • 我不明白为什么不起作用,您的 powershell 版本是什么?
  • 您好,抱歉回复延迟,我使用的是版本:5.1.18362.1171
猜你喜欢
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 2022-01-28
  • 2016-11-05
  • 1970-01-01
  • 2019-07-22
相关资源
最近更新 更多