Если EntityHandling установлено в 'IgnoreEntites', и
Normalization установлено в 'true', то установка
EntityHandling имеет приоритет относительно сущностей атрибут
символа. Сущность атрибут символа никогда не раскрывается,
если EntityHandling - 'IgnoreEntites'.
1. Обеспечивает заданные по умолчанию атрибуты и сущности,
но только из внутреннего подмножества, не выбирает никакие
внешние сущности.
2. Обеспечивает заданные по умолчанию
атрибуты и сущности из внутреннего подмножества, а также из
внешнего DTD и сущностей.
3. Если возвращается не нулевое
значение, все ошибки проверки правильности возвращаются через
callback. Если возвращается нулевое значение, первые ошибки по
результатам проверки правильности будут в XmlException. Это
активирует состояние ошибки, после чего синтаксический анализ
XmlTextReader дальше не сможет продолжаться.
2.2.1. Как XmlTextWriter генерирует хорошо
сформированный (Well Formed) XML
Рассмотрим, какую функциональность предоставляет
XmlTextWriter для помощи в генерации well-formed XML
документов и обеспечения соответствия спецификации W3C
Extensible Markup Language (XML) 1.0
(http://www.w3.org/TR/1998/REC-xml-19980210):
- Для
WriteAttribute, если используются двойные кавычки,
XmlTextWriter заменит двойных кавычки в тексте (контенте)
значениями атрибут ". Если используются одинарные
кавычки, они будут заменены на значения атрибут
'.
- Для WriteString, XmlTextWriter вычленяет
специальные символы, заменяя их на & < >
и на сущности цифровых символов, когда это требуется. Если
запрос находится в контексте значений атрибут, то также будут
выводиться ' и ". Символьные значения
0x-0x1F закодированы как сущности цифр от � и до
, кроме символов незаполненного пространства 0x9,
0x10 и 0x13.
- Для WriteBase64, XmlTextWriter так кодирует
эти base64 значения, что бы они могли быть прочитаны с
использованием ReadBinary для XmlReader.
- Генерация
префикса пространства имён и генерация декларации xmlns (см.
Namespace Handling by XmlTextWriter).
- Гарантирует, что
элементы xml написаны в правильном порядке. Например, не
допускает существование атрибут вне элемента, блока CDATA
внутри атрибута, или существование нескольких корневых
элементов. Также гарантируется, что декларация -
Значения и формат атрибута xml:space проверены. Следующий
пример верен:
w.WriteAttribute("xml:space", "",
"preserve");
Допустимые значения - "default" и "preserve".
Если параметр - не принимает ни одно из этих значений,
ArgumentException будет сброшен.
- Формат атрибута xml:lang
проверен. Следующий пример не
верен:
w.WriteAttribute("xml:lang", "", "U.S.A.");
В
этом случае ArgumentException будет сброшен, потому что
значение. "U.S.A" не соответствует BNF для идентификаторов
языка как определено в IETF RFC 1766. BNF должны быть
следующие:
Language-Tag = Primary-tag ( "-" Subtag
)*
Primary-tag = 1*8ALPHA
Subtag = 1*8ALPHA
ALPHA =
любые ASCII алфавитно-цифровые значения в диапазонах 65-90 и
97-122.
Здесь подразумевается одна первичная метка и ноль
или большее количество вторичных меток, разделённых символом
"-", где первичная метка и вторичные метки могут иметь от 1 до
8 символов ALPHA ASCII. Фактически, до сих пор коды языков и
значения кодов стран/областей не утверждены. Чтобы определить
код языка, поддерживаемый вашей системой, используйте класс
System.Globalization.CultureInfo.
- Если Close() даёт в
результате недопустимый xml документ,
InvalidOperationException будет сброшен.
XmlWriter не проверяет следующее:
- Недопустимые элементы и имена атрибут символов.
-
Символы Unicode, которые не соответствуют кодировке, не
проявившиеся как символьные сущности.
- Дубли атрибут не
могут быть обнаружены.
- Символы в DOCTYPE pubid или sysid
не проверяются.
- Newlines в значении атрибут записываются,
как и &#A;, так что они сохраняются в соответствии с
принятыми в W3C значениями атрибут, нормализующими
синтаксический анализатор, на подобии XmlTextReader.
2.2.2. Работа с пространствами имён средствами
XmlTextWriter
XmlTextWriter поддерживает стек пространства имён,
соответствующий всем пространствам имён, определенных текущим
стеком элемента. Например:
XmlTextWriter w = new
XmlTextWriter(Console.Out);
w.WriteStartElement("root","urn:1");
w.WriteStartElement("item","urn:1");
w.WriteEndElement();
w.WriteEndElement();
w.Close();
В результате получим следующее:
<root xmlns="urn:1"><item/></root>
Обратите внимание, что декларация пространства имён для
вложенного элемента item не выполняется повторно.
Генерация префиксов
Если атрибутам установлена связь с пространством имён URI,
то они должны иметь префикс, соответствующий "Namespace
Defaulting"
(http://www.w3.org/TR/1999/REC-xml-names-19990114/defaulting)
в пространствах имён W3C спецификации Xml, что соответствует
следующему коду:
XmlTextWriter w = new
XmlTextWriter(Console.Out);
w.WriteStartElement("root");
w.WriteAttribute("foo","urn:1",
"123");
w.WriteEndElement();
w.Close();
В результате получим следующее:
<root n1:foo="123" xmlns:n1="urn:1"/>
Примечание: Это справедливо, даже если корневой элемент
связан с заданным по умолчанию пространством имён "URN:1".
Префиксы именованы, как n{i}, где i начинается с 1. Индекс
запускается для каждого следующего элемента, так что, если
вложенный, порождённый элемент также нуждается в
сгенерированном префиксе, "n1" будут использоваться повторно.
Такая организация помогает автору генерировать канонический
Xml, соответствующий "W3C Canonical XML Version 1.0
specification". (http://www.w3.org/TR/sec-namespaces).
Описание деклараций пространства имён вручную
Вы также можете включить код декларации пространства имён
вручную. Это полезно, если Вы знаете, как лучше оптимизировать
число деклараций пространства имён. Делается это следующим
образом:
w.WriteStartElement("root");
w.WriteAttribute("xmlns",
"x", null,
"urn:1");
w.WriteStartElement("item","urn:1");
w.WriteEndElement();
w.WriteStartElement("item","urn:1");
w.WriteEndElement();
w.WriteEndElement();
В результате получим следующее:
<root
xmlns:x="urn:1">
<x:item/>
<x:item/>
</x:root>
В этом примере, декларация пространства имён сдвигается к
корневому элементу, чтобы избежать дублирования для двух
порожденных элементов. Элементы - также приобретает
префикс от декларации пространства имён.
Отмена деклараций пространства имён
Вы можете вручную отменять пространство имён, связанное с
данным префиксом следующим образом:
w.WriteStartElement("x","node","123");
w.WriteAttribute("xmlns","x",null,"bar");
В результате получим следующее:
<x:node xmlns:x="bar"/>
Заметьте, что "bar" отменяет первоначальное пространство
имён URI "123". Это добавляет гибкости для распределённых
приложений.
Определение префиксов
Вы можете передавать префикс для использования. Для этого
существует два способа. Первый, явно использует методы,
которые вызывают префикс:
XmlTextWriter w = new
XmlTextWriter(Console.Out);
w.WriteStartElement("x","root","urn:1");
w.WriteStartElement("y","item","urn:1");
w.WriteEndElement();
w.WriteEndElement();
w.Close();
В результате получим следующее:
<x:root xmlns:x="urn:1"><y:item
xmlns:y="urn:1"/></x:root>
Заметьте, что оба префикса "x" и "y" сохранились.
Обратите внимание: Определение префикса и пустого
пространства имён URI нарушает Section 2 W3C пространства имён
в спецификации Xml
(http://www.w3.org/TR/1999/REC-xml-names-19990114/ns-decl).
Множественные декларации пространств имён
Когда есть множественные декларации пространства имён,
отображающие различные префиксы одному и тому же URN,
XmlWriter выбирает самый близкий стек деклараций пространства
имён следующим образом:
XmlTextWriter w = new
XmlTextWriter(Console.Out);
w.WriteStartElement("x","root","urn:1");
w.WriteStartElement("y","item","urn:1");
w.WriteAttribute("foo","urn:1","bar");
w.WriteEndElement();
w.WriteEndElement();
w.Close();
В этом случае, запрос WriteAttribute не определил никакой
префикс (так что Вы можете выбирать любые префиксы). XmlWriter
находит сначала префикс "y" и использует его, чтобы
воспроизвести следующее:
<x:root
xmlns:x="urn:1">
<y:item
y:foo="bar" xmlns:y="urn:1"/>
</x:root>
Возможности разрешения конфликтов
Любая из предшествующих процедур может порождать конфликты,
для разрешения которых XmlWriter генерирует дополнительные
префиксы. В следующем примере атрибут будет иметь тот же самый
префикс, что и элемент, но пространства имён будут
отличаться:
w.WriteStartElement("x","root","urn:1");
w.WriteAttribute("x","foo","urn:2",
"123");
w.WriteEndElement();
Атрибуту "foo" присваивается новый префикс следующим
образом:
<x:root n1:foo="123" xmlns:n1="urn:2"
xmlns:x="urn:1"/>
Эти конфликты могут случаться только в атрибутах. Для
вложенных элементов, новая декларация пространства имён может
просто переопределяться, как у двойных префиксные областей.
Например, рассмотрим следующий код:
w.WriteStartElement("x","root","urn:1");
w.WriteStartElement("x","item","urn:2");
w.WriteEndElement();
w.WriteEndElement();
В результате получим следующее:
<x:root
xmlns:x="urn:1">
<x:item
xmlns:x="urn:2"/>