读取异常 xml 的节点 - XmlDocument - 表达式必须计算为节点集
Read node of unusual xml - XmlDocument - Expression must evaluate to a node-set
我已经阅读并尝试了很多线程 - this answer, this and this answer。但是,它们不适用于我,因为我真的不习惯 xml:
var xmlString = @"<?xml version=""1.0"" encoding=""windows-1251""?>
<GetReply>
<InformOne>87</InformOne>
<InfoReply>
<![CDATA[<?xml version='1.0' encoding='UTF-8'?>
<S:Container xmlns:S=""http://schemas.xmlsoap.org/soap/envelope/"">
<S:Body>
<ns2:getReference31IPOResponse xmlns:ns2 = ""http://service.one.com/"" >
<return>
<reference31_1IPO xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:nil=""true""/>
<reference31_2IPO xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:nil=""true""/>
<amount>0</amount>
<codeTypeObject>0</codeTypeObject>
<returnCode>4</returnCode>
<errorCode>0</errorCode>
<errorMessage>Something was wrong</errorMessage>
<title>Foo Data</title>
</return>
</ns2:getReference31IPOResponse>
</S:Body>
</S:Container>]]>
</InfoReply>
</GetReply>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
var errorMessage = xmlDoc.SelectSingleNode("/GetReply/InformOne/InfoReply/CDATA/S:Container/S:Body/ns2:getReference31IPOResponse/return/errorMessage");
但是,我看到以下错误:
'Expression must evaluate to a node-set.'
此外,我什至尝试获取InfoReply
,但错误是相同的:
var errorMessage = xmlDoc.SelectSingleNode("/GetReply/InformOne/InfoReply/");
我想要的是读取errorMessage
节点中的文本?
你能告诉我,我做错了什么吗?
任何帮助将不胜感激。
看起来 <![CDATA[<?xml version='1.0' encoding='UTF-8'?>
无法读取其余节点。
我不知道为什么 xml 中有 CData 块。我删除了 CData 并使用了以下 xml
<?xml version="1.0" encoding="windows-1251"?>
<GetReply>
<InformOne>87</InformOne>
<InfoReply>
<S:Container xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getReference31IPOResponse xmlns:ns2 = "http://service.one.com/" >
<return>
<reference31_1IPO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<reference31_2IPO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<amount>0</amount>
<codeTypeObject>0</codeTypeObject>
<returnCode>4</returnCode>
<errorCode>0</errorCode>
<errorMessage>Something was wrong</errorMessage>
<title>Foo Data</title>
</return>
</ns2:getReference31IPOResponse>
</S:Body>
</S:Container>
</InfoReply>
</GetReply>
然后使用以下 xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
Dictionary<string, string> dict = doc.Descendants().Where(x => x.Name.LocalName == "return")
.FirstOrDefault().Elements().Where(x => (string)x != string.Empty)
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
1 - 您忘记了名称空间,您需要添加它们
XmlNamespaceManager
2 - 您还需要将 Xml
分成两个 sub Xml
,一个在 CDATA
之前,另一个在它之后。
将您的代码更改为:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDoc.NameTable);
mgr.AddNamespace("S", "http://schemas.xmlsoap.org/soap/envelope/");
mgr.AddNamespace("ns2", "http://service.one.com/");
mgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
var infoReply = xmlDoc.SelectSingleNode("//GetReply/InfoReply", mgr);
XmlDocument requestDocument = new XmlDocument();
requestDocument.LoadXml(infoReply.InnerText);
var errorMessageNode = requestDocument.SelectSingleNode("/S:Container/S:Body/ns2:getReference31IPOResponse/return/errorMessage", mgr);
string errorMessage = errorMessageNode?.InnerText;
希望对你有所帮助。
我已经阅读并尝试了很多线程 - this answer, this and this answer。但是,它们不适用于我,因为我真的不习惯 xml:
var xmlString = @"<?xml version=""1.0"" encoding=""windows-1251""?>
<GetReply>
<InformOne>87</InformOne>
<InfoReply>
<![CDATA[<?xml version='1.0' encoding='UTF-8'?>
<S:Container xmlns:S=""http://schemas.xmlsoap.org/soap/envelope/"">
<S:Body>
<ns2:getReference31IPOResponse xmlns:ns2 = ""http://service.one.com/"" >
<return>
<reference31_1IPO xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:nil=""true""/>
<reference31_2IPO xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:nil=""true""/>
<amount>0</amount>
<codeTypeObject>0</codeTypeObject>
<returnCode>4</returnCode>
<errorCode>0</errorCode>
<errorMessage>Something was wrong</errorMessage>
<title>Foo Data</title>
</return>
</ns2:getReference31IPOResponse>
</S:Body>
</S:Container>]]>
</InfoReply>
</GetReply>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
var errorMessage = xmlDoc.SelectSingleNode("/GetReply/InformOne/InfoReply/CDATA/S:Container/S:Body/ns2:getReference31IPOResponse/return/errorMessage");
但是,我看到以下错误:
'Expression must evaluate to a node-set.'
此外,我什至尝试获取InfoReply
,但错误是相同的:
var errorMessage = xmlDoc.SelectSingleNode("/GetReply/InformOne/InfoReply/");
我想要的是读取errorMessage
节点中的文本?
你能告诉我,我做错了什么吗? 任何帮助将不胜感激。
看起来 <![CDATA[<?xml version='1.0' encoding='UTF-8'?>
无法读取其余节点。
我不知道为什么 xml 中有 CData 块。我删除了 CData 并使用了以下 xml
<?xml version="1.0" encoding="windows-1251"?>
<GetReply>
<InformOne>87</InformOne>
<InfoReply>
<S:Container xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getReference31IPOResponse xmlns:ns2 = "http://service.one.com/" >
<return>
<reference31_1IPO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<reference31_2IPO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<amount>0</amount>
<codeTypeObject>0</codeTypeObject>
<returnCode>4</returnCode>
<errorCode>0</errorCode>
<errorMessage>Something was wrong</errorMessage>
<title>Foo Data</title>
</return>
</ns2:getReference31IPOResponse>
</S:Body>
</S:Container>
</InfoReply>
</GetReply>
然后使用以下 xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
Dictionary<string, string> dict = doc.Descendants().Where(x => x.Name.LocalName == "return")
.FirstOrDefault().Elements().Where(x => (string)x != string.Empty)
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
1 - 您忘记了名称空间,您需要添加它们
XmlNamespaceManager
2 - 您还需要将 Xml
分成两个 sub Xml
,一个在 CDATA
之前,另一个在它之后。
将您的代码更改为:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDoc.NameTable);
mgr.AddNamespace("S", "http://schemas.xmlsoap.org/soap/envelope/");
mgr.AddNamespace("ns2", "http://service.one.com/");
mgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
var infoReply = xmlDoc.SelectSingleNode("//GetReply/InfoReply", mgr);
XmlDocument requestDocument = new XmlDocument();
requestDocument.LoadXml(infoReply.InnerText);
var errorMessageNode = requestDocument.SelectSingleNode("/S:Container/S:Body/ns2:getReference31IPOResponse/return/errorMessage", mgr);
string errorMessage = errorMessageNode?.InnerText;
希望对你有所帮助。