Вопрос: Как должен обрабатываться символ «\ t» в значениях атрибутов XML?


Кажется, я нашел что-то несоответствие между различными реализациями XML внутри .Net 3.5, и я изо всех сил пытаюсь понять, что является номинально правильным.

Проблема на самом деле довольно легко воспроизвести:

  1. Создайте простой XML-документ с текстовым элементом, содержащим символы «\ t» и присвойте ему атрибут, содержащий символы «\ t»:

    var xmlDoc = new XmlDocument { PreserveWhitespace = false, };
    xmlDoc.LoadXml("<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>");
    xmlDoc.Save(@"d:\TabTest.xml");
    

    NB: Это означает, что сам XmlDocument вполне доволен символами '\ t' в атрибуте value.

  2. Загрузите документ с помощью нового XmlTextReader:

    var rawFile = XmlReader.Create(@"D:\TabTest.xml");
    var rawDoc = new XmlDocument();
    rawDoc.Load(rawFile);
    
  3. Загрузите документ с помощью XmlReader.Create:

    var rawFile2 = new XmlTextReader(@"D:\TabTest.xml");
    var rawDoc2 = new XmlDocument();
    rawDoc2.Load(rawFile2);
    
  4. Сравните документы в отладчике:

    (rawDoc).InnerXml   "<test><text attrib=\"Tab' 'space' '\">Tab'\t'space' '</text></test>"   string
    (rawDoc2).InnerXml  "<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>"  string
    

Чтение документа с использованием нового XmlTextReader было тем, что я ожидал, и значение «\ t» в текстовом значении и значении атрибута было таким, как ожидалось. Однако, если вы посмотрите на документ, прочитанный XmlReader.Create, вы обнаружите, что символ '\ t' в значении атрибута будет преобразован в ' ' персонаж.

Что за....!! :-)

После небольшого поиска Google я обнаружил, что могу кодировать '\ t' как '& # x9;' - если бы я использовал это вместо «\ t» в примере XML, оба читателя работали, как ожидалось.

Теперь Altova XmlSpy и другие другие читатели XML, по-видимому, совершенно довольны символами '\ t' в значениях атрибутов, мой вопрос в том, что является правильным способом справиться с этим?

Должен ли я писать XML-файл с символами «\ t», закодированными в значениях атрибутов, таких как XmlReader.Create, или другие инструменты XML правильно, а символы «\ t» действительны и XmlReader.Create нарушен?

В каком направлении я должен пойти, чтобы исправить / решить эту проблему?


5


источник


Ответы:


Возможно, что-то связано с нормализацией значения атрибута. Для атрибутов CDATA для замены строк и вкладок значений атрибутов для пространственных символов требуется парсер XML, если они не записаны в экранированной форме как ссылки на символы.


2



Проверять, выписываться XmlReaderSettings.ComformanceLevel , В частности, это описание:

Обратите внимание, что объекты XmlReader, созданные методом Create, по умолчанию совместимы с классом XmlTextReader. Ниже приведены улучшения совместимости, которые не включены в XmlTextReader, но доступны по умолчанию для считывателей, созданных методом Create


1



С первого взгляда кажется, что XmlTextReader является не  совместимый с рекомендацией W3C. См. Раздел в рекомендация  при нормализации значения атрибута, в частности

Для символа пробела (# x20, #xD, #xA, # x9) добавьте пробельный символ (# x20) к нормализованному значению.

Следовательно, поведение, которого вы не ожидали (видя пробел вместо закладки), на самом деле является правильным рекомендуемым поведением.

Я не имею понятия почему XmlTextReader ведет себя таким образом (в документации нет ничего), однако, похоже, вы, похоже, уже определили правильное обходное решение - закодируйте атрибут как &#x9; вместо. В этом случае нормализованная строка будет содержать сам символ табуляции.


1



@all: Спасибо за все ваши ответы и комментарии.

Казалось бы, Justin и Michael Kay верны, а пробел должен быть закодирован в соответствии со спецификациями W3C XML и что проблема заключается в том, что значительное количество реализаций MS не соблюдает это требование.

В моем случае спецификация XML в стороне, все, что я действительно хочу, - это правильное сохранение значений атрибутов, т. Е. Сохраненные значения должны быть точно прочитанными значениями.

Ответ на это заключается в том, чтобы принудительно использовать XmlWriter, созданный с помощью метода XmlWriter.Create при сохранении файлов XML в первую очередь.

Хотя Dataset и XmlDocument предоставляют механизмы сохранения / записи, ни один из них не корректно кодирует пробелы в атрибутах при использовании в форме по умолчанию. Однако, если я вынуждаю их использовать созданный вручную XmlWriter, правильная кодировка применяется и записывается в файл.

Таким образом, исходный файл сохраняет код:

var xmlDoc = new XmlDocument { PreserveWhitespace = false, };
xmlDoc.LoadXml("<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>");

using (var xmlWriter = XmlWriter.Create(@"d:\TabTest.Encoded.xml"))
{
    xmlDoc.Save(xmlWriter);
}

Затем этот автор правильно кодирует белое пространство симметричным образом для чтения XmlReader.Create, не изменяя значения атрибута.

Другое замечание заключается в том, что это решение полностью инкапсулирует кодировку из моего кода, когда считыватель и писатель прозрачно выполняют кодирование и декодирование при чтении и записи.


1