У меня есть XML-файл, и я хочу прочитать все строки с помощью инструментов класса XmlTextReader. Ниже приведен пример файла xml:
<?xml version="1.0" encoding="utf-8"?>
<CodeSigns>
<CodeSign Format="1.0.0">
<Header>
<Title>AAA</Title>
<Shortcut>AAA</Shortcut>
<Description>AAA</Description>
<Author>Viva</Author>
<LoadTypes>
<LoadType>Expansion</LoadType>
</LoadTypes>
</Header>
<Sign>
<Declarations />
<Code Language="SQL Server" Kind="SQL Server"><![CDATA[SELECT TOP 100 [Id]
,[TotalSeconds]
,CAST('<![CDATA[' + [Parameters] + ']]]]><![CDATA[>' AS XML) as [Parameters]
,CAST('<![CDATA[' + [Query] + ']]]]><![CDATA[>' AS XML) as [Query]
,CAST('<![CDATA[' + [StackTrace] + ']]]]><![CDATA[>' AS XML) as [StackTrace]
,[CreateDate]
,[MachineName]
,[UserName]
,CAST('<![CDATA[' + [Exception] + ']]]]><![CDATA[>' AS XML) as [Exception]
,CAST('<![CDATA[' + [InnerException] + ']]]]><![CDATA[>' AS XML) as [InnerException]
,[CommandType]
FROM [QMaster].[dbo].[LogSlowQueries]
where CreateDate > CONVERT(DATE,GETDATE())
order by totalseconds desc]]>
</Code>
</Sign>
</CodeSign>
</CodeSigns>
Нам нужен элемент, чтобы прочитать все, что он включает. Остальные элементы для нас не важны, но с этим есть проблемы, потому что вместо трех были прочитаны только три строки. Код C #, используемый для чтения этого файла, приведен ниже:
public void Load(string path) {
filename = Path.GetFileName(path);
try {
using (XmlTextReader reader = new XmlTextReader(path)) {
while (reader.Read()) {
if (reader.NodeType == XmlNodeType.Element) {
switch (reader.Name) {
case "Title":
title = ReadProperty(reader);
break;
case "ToolTip":
tooltip = ReadProperty(reader);
break;
case "Description":
description = ReadProperty(reader);
break;
case "Author":
author = ReadProperty(reader);
break;
**case "Code":
language = reader.GetAttribute("Language");
code = ReadProperty(reader);
break;**
}
}
}
}
}
catch (XmlException) {
}
}
private string ReadProperty(XmlReader reader) {
if (reader.IsEmptyElement)
return string.Empty;
reader.Read();
return reader.Value;
}
Нам нужно получить все строки из XmlNodeType.Element с именем «Code». Это должно быть прочитано все со всеми строками в этом. Однако мы получаем в reader.Value только три строки на картинке:
Большое спасибо за ответы
Во-первых, поговорим о форматировании.
Если xml отформатирован именно так, как показано в вопросе:
<Code Language="SQL Server" Kind="SQL Server"><![CDATA[SELECT TOP 100 [Id]
т. е. содержимое элемента Code
начинается в этой же строке, тогда результат будет как у вас.
Однако, если форматирование будет таким:
<Code Language="SQL Server" Kind="SQL Server">
<![CDATA[SELECT TOP 100 [Id]
т. е. содержимое начинается со следующей строки, то ваш код вернёт строку, состоящую из пробелов. А именно такой формат получился, когда я вставил ваш xml в редактор Visual Studio (Студия сама его отформатировала).
Вы обязаны проверять в методе ReadProperty
, до какого узла дошли, а не просто слепо полагаться на жёстко-заданный формат. Потому что в соответствии со стандартом, xml имеет право быть отформатированным как угодно.
Свойство reader.Value
возвращает содержимое текущего узла. Этим узлом может быть не только Element
, как вероятно вы ожидали, но и CDATA
, и Whitespace
. Соответственно, возвращается либо содержимое первого блока CDATA
(три строки текста), либо пробельная строка.
Во-вторых, блоки CDATA
не могут быть вложенными. Посмотрите, как их подсвечивает xml-редактор Visual Studio:
По-хорошему каждый из этих блоков нужно закрывать скобкой ]]>
перед началом следующего. Или, что проще и разумнее (на мой взгляд), оставить один-единственный блок CDATA
.
Ваш метод ReadProperty
можно заменить одной строкой:
reader.ReadElementContentAsString()
При этом будет прочитано всё содержимое элемента Code
как одно целое. При этом текст будет извлечён из CDATA
. Но только из тех блоков, которые парсер распознает как самостоятельные (не вложенные)! См. выше картинку.
Что делать с оставшимися кусками блоков CDATA
? Проблему нужно решать уровнем выше: при записи/создании xml.
Возможно, вас устроит чтение без извлечения из блоков CDATA
. Для этого используйте
var code = reader.ReadInnerXml();
Напоследок замечу, что класс XmlRextReader считается устаревшим, как и написано в документации.
Поэтому я бы заменил строку
using (XmlTextReader reader = new XmlTextReader(path))
на следующую
using (var reader = XmlReader.Create(path))
Но это соверщенно не важно.
Решение найдено, все работает:
private string ReadProperty(XmlReader reader) {
if (reader.IsEmptyElement)
return string.Empty;
reader.Read();
var st1 = reader.Value;
while (reader.Read()) {
if (reader.NodeType == XmlNodeType.CDATA)
st1 += reader.Value;
}
return st1;
}
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Нужно вставлять картинки за место слов в тексте в RichTextBox, соответственно что бы обтекание было слева и справа
Имеется вот такая панель кнопок, в ScrollViewer1 вложен StackPanel с сотней кнопок, на каждой кнопке SteckPanel с Image, CheckBox и TextBlock, CheckBox управляет видимостью...
На сайте есть скрипт обработчик, при попытке соединится через mysql_connect ничего не получаетсяСкрипт лежит просто в корневой папке
Здравствуйте, решил сделать рассылку писем через smtp, используя данный скрипт на php:http://i-leonru/smtp-php/