调用Risport70获取CUCM电话实时数据时XML节点解析异常求助
问题:CUCM RIS API返回的ns1:CMNodes节点无法正常解析(PowerShell)
我在通过PowerShell调用CUCM的RISService70获取电话实时信息时遇到异常:前面的节点都能正常钻取,但访问*<ns1:CMNodes>*节点后,其下所有子节点被合并成一个大字符串,无法通过Select-Node等方式查询子节点。
调用代码如下:
$RisBody = "<soapenv:Envelope xmlns:soapenv=`"http://schemas.xmlsoap.org/soap/envelope/`" xmlns:soap=`"http://schemas.cisco.com/ast/soap`"> <soapenv:Header/> <soapenv:Body> <soap:selectCmDevice> <soap:StateInfo></soap:StateInfo> <soap:CmSelectionCriteria> <soap:MaxReturnedDevices>1000</soap:MaxReturnedDevices> <soap:DeviceClass>Phone</soap:DeviceClass> <soap:Model>255</soap:Model> <soap:Status>Any</soap:Status> <soap:NodeName></soap:NodeName> <soap:SelectBy>Name</soap:SelectBy> <soap:SelectItems> <soap:item> <soap:Item>SEPABCDEF123456</soap:Item> </soap:item> </soap:SelectItems> <soap:Protocol>Any</soap:Protocol> <soap:DownloadStatus>Any</soap:DownloadStatus> </soap:CmSelectionCriteria> </soap:selectCmDevice> </soapenv:Body> </soapenv:Envelope>" $RisRequest = Invoke-RestMethod 'https://CUCM:8443/realtimeservice2/services/RISService70?wsdl' -Method 'POST' -Headers $headers -Body $RisBody
我尝试过Invoke-WebRequest、将InnerXml/OuterXml转为[xml]类型,均未解决问题,似乎RisPort70在<CMNodes>节点后将所有内容转为字符串,请问是否必须通过粗暴方式解析?
解决方案
不用粗暴解析,问题出在RIS API的命名空间处理和PowerShell的XML解析逻辑上,试试以下几种可行方案:
1. 重新包裹CMNodes片段为完整XML文档
提取<CMNodes>的原始XML字符串,补上正确的命名空间后转为XML对象:
# 获取CMNodes的原始内容字符串 $cmNodesRaw = $RisRequest.Envelope.Body.selectCmDeviceResponse.selectCmDeviceReturn.SelectCmDeviceResult.cmnodes.InnerXml # 用带命名空间的根节点包裹片段,生成完整XML $cmNodesXml = [xml]"<root xmlns:soap='http://schemas.cisco.com/ast/soap'>$cmNodesRaw</root>" # 现在可以正常查询子节点,比如获取所有Node节点 $cmNodesXml.SelectNodes("//soap:Node")
2. 使用命名空间管理器直接查询原始XML
给原始XML对象添加命名空间管理器,指定RIS API的命名空间后直接查询:
# 创建命名空间管理器 $nsManager = New-Object System.Xml.XmlNamespaceManager($RisRequest.NameTable) $nsManager.AddNamespace("soap", "http://schemas.cisco.com/ast/soap") # 直接查询<CMNodes>下的子节点 $RisRequest.SelectNodes("//soap:CMNodes/soap:Node", $nsManager)
3. 改用Invoke-WebRequest手动解析XML
Invoke-RestMethod可能会自动处理命名空间导致节点被转成字符串,换成Invoke-WebRequest后手动解析:
$response = Invoke-WebRequest -Uri 'https://CUCM:8443/realtimeservice2/services/RISService70?wsdl' -Method POST -Headers $headers -Body $RisBody $xmlResponse = [xml]$response.Content # 添加命名空间管理器并查询 $nsManager = New-Object System.Xml.XmlNamespaceManager($xmlResponse.NameTable) $nsManager.AddNamespace("soap", "http://schemas.cisco.com/ast/soap") $xmlResponse.SelectNodes("//soap:CMNodes/soap:Node", $nsManager)
原因说明
RISService70返回的XML中,<CMNodes>节点下的子节点使用了默认命名空间,但PowerShell的Invoke-RestMethod在自动解析时,没有正确处理嵌套的命名空间关联,导致子节点被识别为纯文本字符串。通过手动添加命名空间或重新包裹XML片段,可以让解析器正确识别节点结构。
内容的提问来源于stack exchange,提问作者sdcrytek
相关产品推荐
相关产品推荐

