Спарсить из xml документа

311
24 мая 2017, 03:40

Есть xml, полученный из Excel. Разметка выглядит примерно так, только строк значительно больше и блок Data c "Number" только один:

XML:

<Row>
  <Cell>
    <Data ss:Type="String">AAPL US Equity</Data>
  </Cell>
  <Cell>
    <Data ss:Type="Number">150.25</Data>
  </Cell>
  <Cell>
    <Data ss:Type="Number">1</Data>
  </Cell>
</Row>
<Row>
  <Cell>
    <Data ss:Type="String">GOOGL Equity</Data>
  </Cell>
  <Cell>
    <Data ss:Type="Number">942.17</Data>
  </Cell>
  <Cell>
    <Data ss:Type="Number">2</Data>
  </Cell>
</Row>
<Row>...</Row>
<Row>...</Row>

Использую XmlTextReader, чтобы выбрать все значения из блока <Data ss:Type="String">ВОТ ЭТО</Data > (AAPL US Equity и GOOGL Equity):

public void Go()
{
    XmlTextReader ValueReader = new XmlTextReader("///book1.xml");
    try
    {
        while (ValueReader.Read())
        {
            switch (ValueReader.NodeType)
            {
                case XmlNodeType.Element:
                    if (ValueReader.Name == "Cell")
                    {
                        ValueReader.MoveToElement();
                        var X = ValueReader.ReadOuterXml();
                        XmlDocument usdXmlDocument = new XmlDocument();
                        usdXmlDocument.LoadXml(X);
                        XmlNode xmlNode = usdXmlDocument.SelectSingleNode(@"Data ss:Type=""String""/Data");
                        MessageBox.Show(xmlNode.InnerText.ToString(), "");
                    }
                    break;
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, ex.Source);
    }
}

Исключение

Data ss:Type="String"/Number имеет недопустимый указатель(токен).

Буду благодарен за любую подсказку.

Answer 1

В метод SelectSingleNode нужно передавать xpath-выражение. Вот это - @"Data ss:Type=""String""/Data" - что-то странное, но никак не xpath.

Если использовать именно ваш алгоритм извлечения данных, с применением XmlDocument, то минимальные изменения, которые нужно внести в код, это взять правильный xpath и добавить менеджер пространств имён. Пространства имён обязательно нужно учитывать, без этого никак.

var manager = new XmlNamespaceManager(usdXmlDocument.NameTable);
manager.AddNamespace("ss", "some-namespace");
XmlNode xmlNode = usdXmlDocument.SelectSingleNode(@"/Cell/Data[@ss:Type='String']", manager);
if (xmlNode != null)
    MessageBox.Show(xmlNode.InnerText.ToString(), "");

Вместо some-namespace укажите именно то, что у вас в XML. Где его взять? Ищите в своём xml объявление наподобие xmlns:ss="some-namespace". Вероятнее всего, оно будет в самом начале, в корневом элементе документа.

Код можно существенно упростить и ускорить его работу.

Класс XmlTextReader считается устаревшим. Вместо него следует создавать экземпляры XmlReader с помощью статического метода Create.

После использования все Disposable объекты следует освобождать. Проще всего это делать с применением конструкции using.

Класс XmlReader имеет много полезных методов. В нашем случае - однородная структура xml - удобно применить ReadToFollowing. А для чтения атрибута - GetAttribute. Пространство имён при этом обязательно нужно указывать! Естественно, заменить some-namespace на настоящий.

Найдя элемент с нужным атрибутом, читаем его значение ReadElementContentAsString.

using (var reader = XmlReader.Create("test.xml"))
{
    while (reader.ReadToFollowing("Data"))
    {
        if (reader.GetAttribute("Type", "some-namespace") == "String")
            MessageBox.Show(reader.ReadElementContentAsString());
    }
}

Это весь код!

READ ALSO
Android. Запретить выход из приложения

Android. Запретить выход из приложения

Стоит задача сделать приложение для отзывовРаботать оно будет на планшете, доступном клиентам

751
Передать несколько значений в параметр report builder

Передать несколько значений в параметр report builder

Как программно передать в параметр отчета несколько значений? Я передаю так :

231
Асинхронный сервер для игры

Асинхронный сервер для игры

Нужно написать сервер наNet-Core, Игра в целом пошаговая один на один, но во время хода противника можно слать эмоции как в Heartstone, так что последовательно...

247
Не появляется dataGridViewComboboxCell

Не появляется dataGridViewComboboxCell

Есть формаНа ней dataGridView

265