Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Странное поведение XmlReader / 12 сообщений из 12, страница 1 из 1
25.02.2014, 13:28
    #38571537
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Столкнулся со странностью, которую не могу объяснить.
Есть код
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
using (XmlReader reader = XmlReader.Create(input))
{
	for (reader.MoveToContent(); reader.Read(); )
		if (reader.NodeType == XmlNodeType.Element)
			switch (reader.Name)
			{
				case "row":
					break;

				case "c":
					string strValue = reader.ReadElementString();
					break;
			}
}


который читает XML файл
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<row r="2" spans="1:20" ht="35.1" customHeight="1" x14ac:dyDescent="0.2">
<c r="A2" s="9"/>
<c r="B2" s="9"/>
<c r="C2" s="9"/>
<c r="D2" s="9"/>
<c r="E2" s="9"/>
<c r="F2" s="9"/>
<c r="G2" s="9"/>
<c r="H2" s="9"/>
<c r="I2" s="1" t="s"><v>7</v></c>
<c r="J2" s="1" t="s"><v>8</v></c>
<c r="K2" s="1" t="s"><v>9</v></c>
<c r="L2" s="1" t="s"><v>10</v></c>
<c r="M2" s="1" t="s"><v>11</v></c>
<c r="N2" s="1" t="s"><v>12</v></c>
<c r="O2" s="1" t="s"><v>13</v></c>
<c r="P2" s="1" t="s"><v>14</v></c>
<c r="Q2" s="1" t="s"><v>15</v></c>
<c r="R2" s="1" t="s"><v>16</v></c>
<c r="S2" s="1" t="s"><v>17</v></c>
<c r="T2" s="1" t="s"><v>18</v></c>
</row>


Так вот, reader читает элементы "c" с пропусками. Т.е.
<c r="A2" s="9"/>
<c r="C2" s="9"/>
<c r="F2" s="9"/>
не подряд. Почему, не могу понять. В отладчике ровно так - перескакивает через записи.
Дойдя до
<c r="I2" s="1" t="s"><v>7</v></c>
снова читает все подряд, так как нужно.
Кто сталкивался?
...
Рейтинг: 0 / 0
25.02.2014, 14:12
    #38571595
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Либо вы что-то не привели в коде, либо смотрите что-то не то:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
using (var sr = new StringReader(Properties.Resources.XData))
using (var reader = XmlReader.Create(sr))
{
  for (reader.MoveToContent(); reader.Read(); )
    if (reader.NodeType == XmlNodeType.Element)
      switch (reader.Name)
      {
        case "row":
          break;

        case "c":
          reader.MoveToAttribute("r");
          reader.ReadAttributeValue();
          var info = string.Format("{0} {1}", ((IXmlLineInfo)reader).LineNumber, reader.Value);
          reader.MoveToElement();
          Console.WriteLine("{0} {1}", info, reader.ReadElementString());
          break;
      }
}


Вывод:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
2 A2
3 B2
4 C2
5 D2
6 E2
7 F2
8 G2
9 H2
10 I2 7
11 J2 8
12 K2 9
13 L2 10
14 M2 11
15 N2 12
16 O2 13
17 P2 14
18 Q2 15
19 R2 16
20 S2 17
21 T2 18
...
Рейтинг: 0 / 0
25.02.2014, 14:34
    #38571633
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Код конечно указан не весь. Вот как было
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
                            case "c":
                                span = reader.GetAttribute("s");
                                type = reader.GetAttribute("t");
                                reff = reader.GetAttribute("r");

                                reader.MoveToElement();
                                string strValue = reader.ReadElementString();
                                ...



Переделал с учетом вашего предложения.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
                            case "c":
                                reader.MoveToAttribute("r");
                                reader.ReadAttributeValue();
                                reff = reader.Value.ToString();

                                reader.MoveToAttribute("s");
                                reader.ReadAttributeValue();
                                span = reader.Value.ToString();

                                reader.MoveToAttribute("t");
                                reader.ReadAttributeValue();
                                type = reader.Value.ToString();

                                reader.MoveToElement();
                                string strValue = reader.ReadElementString();
                                ...



Только результат один. Отрицательный.
...
Рейтинг: 0 / 0
25.02.2014, 14:41
    #38571644
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Беда еще в том, что если подсунуть коду XML, то он читает его правильно.
Но если читать из Stream объекта FileUpload, то такое странное чтение.
...
Рейтинг: 0 / 0
25.02.2014, 15:35
    #38571762
Sergey S
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Как формируется XML?
Может проблема в этом?
т.е. предполагаю - что теги "с" - строятся по какому то условию, и перепутана буква латиница "с" и русская "с"
...
Рейтинг: 0 / 0
25.02.2014, 15:44
    #38571775
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Sergey SКак формируется XML?
Может проблема в этом?
т.е. предполагаю - что теги "с" - строятся по какому то условию, и перепутана буква латиница "с" и русская "с"

Если бы... Только файл стандартнее некуда. Распакованный XML из Windows Excel 2007 (*.xlsx).
Впрочем могу приложить, можете сами убедиться, что там все нормально.

Не исключаю вариант, что взятый по отдельности он будет читаться без проблем.
Может эти косяки только у меня на компе.
...
Рейтинг: 0 / 0
25.02.2014, 16:39
    #38571905
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
SQL2008,

на форуме приведён xml с разбиением на строки, а в файле содержимое записано в одну строку. То есть в первом случае между элементами присутствует XmlNodeType.Whitespace, а во втором случае - нет.
Это распространённая ошибка, не учитывать этот момент при ручном разборе xml. Я сам раньше часто на это напарывался.
...
Рейтинг: 0 / 0
25.02.2014, 16:43
    #38571914
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Опытным путем было установлено, что использование
Код: c#
1.
 reader.ReadElementString(); 

приводит к пропускам при чтении.
Отсюда следует, что нужно повнимательнее использовать эту функцию.
Всем спасибо!
Думаю, что далее разрулю косяк самостоятельно.
...
Рейтинг: 0 / 0
25.02.2014, 16:45
    #38571920
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
petalvikна форуме приведён xml с разбиением на строки, а в файле содержимое записано в одну строку. То есть в первом случае между элементами присутствует XmlNodeType.Whitespace, а во втором случае - нет.
Это распространённая ошибка, не учитывать этот момент при ручном разборе xml. Я сам раньше часто на это напарывался.
Я бы согласился, но это косячит только в одном месте. Далее все работает как нужно.
Впрочем, похоже, что я нашел проблему (см выше).
...
Рейтинг: 0 / 0
25.02.2014, 16:46
    #38571925
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
А теперь найдите 10 отличий в том примере xml, который был приведен в стартовом постинге, и в том, который в аттаче. Подсказка: форматирование разметки. Пробелы и переносы строк между узлами - это тоже узлы xml, и ридер движется по ним - если они есть - сообразно вашим командам.
Вот такое:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
using (var sr = new StringReader(Properties.Resources.XData))
using(var reader = XmlReader.Create(sr))
{
  for (reader.MoveToContent(); reader.Read(); )
  {
    if (reader.NodeType != XmlNodeType.Element) continue;
    Console.WriteLine(reader.GetAttribute("r"));
    reader.MoveToElement();
    Console.WriteLine(reader.GetAttribute("r"));
    reader.ReadElementString();
    Console.WriteLine(reader.GetAttribute("r"));
    Console.WriteLine("===============================");
  }
}


на исходном xml c переносом строк даст вот такой вывод:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
A2
A2

===============================
B2
B2

===============================
C2
C2

===============================
D2
D2

===============================
E2
E2

===============================
F2
F2

===============================
G2
G2

===============================
H2
H2

===============================
I2
I2

===============================
...
а на xml в одну строку даст вот такой вывод:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
A2
A2
B2
===============================
C2
C2
D2
===============================
E2
E2
F2
===============================
G2
G2
H2
===============================
I2
I2

===============================
J2
J2
...
Причина в том, что: http://msdn.microsoft.com/en-us/library/hd94a4xh(v=vs.110).aspx
This is a helper method for reading simple text-only elements. It calls MoveToContent to find the next content node and then parses its value as a simple string.
а XmlReader.MoveToContent, в свою очередь
Checks whether the current node is a content (non-white space text, CDATA, Element, EndElement, EntityReference, or EndEntity) node. If the node is not a content node, the reader skips ahead to the next content node or end of file. It skips over nodes of the following type: ProcessingInstruction, DocumentType, Comment, Whitespace, or SignificantWhitespace.
- в случае xml c переносами MoveToContent, неявно вызываемый при ReadElementString, перемещает ридер на пустой текстовый узел,т.к. это вполне себе нода. А в случае с форматированием в одну строку - на следующий элемент.
А если вы отформатируете ваш xml с отступами, то код будет рваться на ReadElementString c ошибкой XmlException: Unexpected node type Element. ReadElementString method can only be called on elements with simple or empty content - т.к. пробельные узлы плюс пустые узлы плюс разметка плюс текст - это уже не simple content (а только тэг и текст - simple).
И вывод из всего этого очень простой: не нужно парсить своими средствами. Получайте XmlDocument/XDocument, нужную инфу извлекайте из них.
...
Рейтинг: 0 / 0
25.02.2014, 16:58
    #38571957
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Сон Веры Павловны и petalvik, большое спасибо, за то, что вывели на правильную дорогу из зарослей заблуждений.
Уж начал сомневаться в состоянии рассудка
...
Рейтинг: 0 / 0
25.02.2014, 17:57
    #38572071
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Странное поведение XmlReader
Переписал код с использованием XmlDocument и глюки исчезли.
Правда при использовании XmlReader-a можно было читать все элементы подряд,
а в XmlDocument приходится учитывать структуру вложенности элементов.
Вопрос исчерпан, тема закрыта.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Странное поведение XmlReader / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]