Чтение узла с необычным xml - XmlDocument - выражение должно вычисляться для набора узлов - PullRequest
0 голосов
/ 13 февраля 2020

Я прочитал и перепробовал много тем - этот ответ , этот и этот ответ . Тем не менее, они не применимы ко мне, поскольку у меня действительно не обычно 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");

Однако я вижу следующую ошибку:

'Выражение должно быть оценено как набор узлов. '

Кроме того, я даже пытался получить InfoReply, но ошибка та же:

var errorMessage = xmlDoc.SelectSingleNode("/GetReply/InformOne/InfoReply/");

Я хочу прочитать текст на errorMessage узел?

Не могли бы вы сказать мне, пожалуйста, что я делаю не так? Любая помощь будет принята с благодарностью.

Похоже, <![CDATA[<?xml version='1.0' encoding='UTF-8'?> прерывает чтение остальных узлов.

Ответы [ 2 ]

2 голосов
/ 13 февраля 2020

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;

Я надеюсь, что это поможет вам.

2 голосов
/ 13 февраля 2020

Я не знаю, почему у вас есть блок CData внутри xml. Я удалил 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());


        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...