Как получить содержимое всех элементов в XML с помощью XMLReader? - PullRequest
0 голосов
/ 14 июля 2020

Я использую XMLReader для чтения всех элементов в данном XML, но содержимое некоторых элементов не извлекается.

Пример:

string msg = string.Empty;
using (XmlReader xReader = XmlReader.Create(new StringReader("<ns3:Failure xmlns:ns3=\"urn:xxxx\"><Code>Unauthorized</Code><Reason>Access denied</Reason><Detail>Invalid username/password.</Detail></ns3:Failure>")))
{
    while (xReader.Read())
    {
        if (xReader.NodeType == XmlNodeType.Element)
        {
            switch (xReader.Name)
            {
                case "Code":
                    msg = msg + " " + xReader.ReadElementContentAsString();
                    break;
                case "Reason":
                    msg = msg + " " + xReader.ReadElementContentAsString();
                    break;
                case "Detail":
                    msg = msg + " " + xReader.ReadElementContentAsString();
                    break;

            }
        }
    }
}

После выполнения вышеуказанного кода , значение msg - «Unauthorized Invalid username / password».
Содержимое <Reason> отсутствует.
Ожидаемое значение должно быть «Unauthorized Access denied Invalid username / password».

Как мне получить содержимое всех элементов?

1 Ответ

1 голос
/ 14 июля 2020

Ваш элемент Reason пропускается, потому что после того, как содержимое Code было прочитано, средство чтения также переместилось к следующему элементу (здесь: Reason), что заставляет последующий вызов Read перемещаться еще на один элемент (здесь: Detail).

Из документации ReadElementAsContentString:

Этот метод считывает начальный тег, содержимое элемента и перемещает средство чтения за тегом конечного элемента.

Есть несколько способов решить эту проблему.

Если вы действительно хотите сохранить switch / case проверка имен элементов, вы должны убедиться, что не вызываете метод Read при вызове ReadElementContentAsString, например:

using (XmlReader xReader = XmlReader.Create(new StringReader("<ns3:Failure xmlns:ns3=\"urn:xxxx\"><Reason>Access denied</Reason><Code>Unauthorized</Code><Detail>Invalid username/password.</Detail></ns3:Failure>")))
{   
    xReader.MoveToContent();
    while (!xReader.EOF)
    {
        if (xReader.NodeType == XmlNodeType.Element)
        {
            switch (xReader.Name)
            {
                case "Code":
                case "Reason":
                case "Detail":
                    msg = msg + " " + xReader.ReadElementContentAsString();
                    break;
                default:
                    xReader.Read();
                    break;
            }
        }
        else
        {
            xReader.Read();
        }
    }
}

В качестве альтернативы, учитывая пример показано в вашем вопросе, вы можете просто объединить все узлы типа XmlNodeType.Text, например:

string msg = string.Empty;
using (XmlReader xReader = XmlReader.Create(new StringReader("<ns3:Failure xmlns:ns3=\"urn:xxxx\"><Reason>Access denied</Reason><Code>Unauthorized</Code><Detail>Invalid username/password.</Detail></ns3:Failure>")))
{
    
    while (xReader.Read())
    {       
        if (xReader.NodeType == XmlNodeType.Text)
        {
            msg = msg + " " + xReader.ReadContentAsString();
        }
    }     
}
...