Что такое пустой элемент?
В соответствии с спецификацией XML это определение пустого элемента:
Элемент без содержимого называется пустым.] Представление пустого элемента является либо начальным тегом, за которым сразу следует конечный тег, либо тег с пустыми элементами.
(см.: http://www.w3.org/TR/REC-xml/#NT-content)
Теперь у меня нет проблем с пониманием тегов с пустыми элементами: <i-am-empty/>
, и недоразумение невозможно. Но мне кажется, что стандарт противоречит самому себе в другом случае: с одной стороны, он говорит, что любой тег без content
пуст, с другой стороны, он говорит, что это может быть представлено начальным тегом, за которым следует сразу конечный тег. Но если мы посмотрим на определение content
:
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
Мне кажется, что content
состоит из двух необязательных частей, CharData?
и группы ()*
. Но поскольку обе эти части являются необязательными, это будет означать, что ничто (как и отсутствие символов) не соответствует этой продукции. SO, если я попытаюсь сопоставить это определение содержимого с тем, что находится внутри <am-i-empty-or-not></am-i-empty-or-not>
, я бы получил положительное совпадение. Итак, с одной стороны, это пустой тег, потому что это "начальный тег, за которым сразу следует конечный тег", с другой стороны, он не пуст, потому что между тегами я могу положительно сопоставлять определение производственного правила [ 43] для содержимого, и в этом случае он содержит контент, что означает, что он не может быть пустым.
Кто-нибудь может объяснить, какие правила имеют приоритет? Кто-нибудь знает о любых реализациях DOM или парсера, которые имеют разные мнения по этому поводу?
Ответы
Ответ 1
Но поскольку обе эти части являются необязательными, это будет означать, что ничто (как и отсутствие символов) не соответствует этой продукции.
Это может быть правдой, но формулировка в спецификации по этому вопросу совершенно ясна. В следующем параграфе есть даже примеры для пустых элементов.
<IMG align="left"
src="http://www.w3.org/Icons/WWW/w3c_home" />
<br></br>
<br/>
Итак, единственный способ (в этом контексте, с окружающими формулировками и примерами) читать
Элемент без содержимого
будет включать "контент, который (при совпадении с производством) полностью пуст" (т.е. нулевая длина, даже не пустое пространство).
Ответ 2
<element />
и
<element></element>
являются пустыми элементами. Любые производные от стандартов должны интерпретироваться таким образом.
Ответ 3
Я хотел проверить, какие разные варианты "пустых" на самом деле пустые.
Вариация A
<Santa/>
дает дерево
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
Вариант B
<Santa></Santa>
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
Вариант C
<Santa>
Space </Santa>
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
Вариация D
<Santa>
Tab </Santa>
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
Вариант E
<Santa>
CRLF
</Santa>
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
Все варианты текста дают одно и то же дерево DOM. Когда XML-документ просят сериализовать себя, дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
выводится сериализованный текст:
<?xml version="1.0"?>
<Santa/>
Вручное добавление пустого текста node
Я хотел посмотреть, что произойдет, если я построю дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
|- NODE_TEXT #text ""
с использованием псевдокода:
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
santa.appendChild(doc.CreateText(""));
Когда этот документ DOM сохраняется в потоке, он выводится как:
<?xml version="1.0"?>
<Santa/>
Даже когда элемент вынужден иметь дочерний элемент (т.е. вынужден не быть пустым), DOM делает его пустым.
Текст команды node с пробелом
И тогда, если я обязательно поставлю некоторые пробелы в TEXT
node:
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
santa.appendChild(doc.CreateText(" "));
Выходит как XML:
<?xml version="1.0" ?>
<Santa> </Santa>
с деревом DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
|- NODE_TEXT #text " "
Интересно; это не кругооборот.
Принудительность TAB CRLF
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
santa.appendChild(doc.CreateText(TAB+LF+CR));
Выходит как XML:
<?xml version="1.0"?>
<Santa>TABLF
CR
</Santa>
с деревом DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
|- NODE_TEXT #text "\t\n\n"
Да, XML преобразует все CR в LF, и да, это не round-trippable. Если вы разбираете:
<?xml version="1.0"?>
<Santa>TABLF
CR
</Santa>
вы получите дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
Настройка element.text
Наконец, мы приходим к тому, что происходит, если вы устанавливаете текст элемента через это свойство .text
.
Не устанавливать текст:
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
//santa.text = ""; example where we don't set the text
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
и XML:
<?xml version="1.0"?>
<Santa/>
Установка пустого текста
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
santa.text = ""; //example where we do set the text
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
|- NODE_TEXT #text ""
и XML:
<?xml version="1.0"?>
<Santa/>
Установка одиночного пространства
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
santa.text = " ";
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
|- NODE_TEXT #text " "
и XML:
<?xml version="1.0"?>
<Santa> </Santa>
Настройка большего количества белого цвета
XmlDocument doc = new XmlDocument();
XmlElement santa = doc.appendChild(doc.CreateElement("Santa"));
santa.text = LF+TAB+CR;
дает дерево DOM:
|- NODE_DOCUMENT #document ""
|- NODE_ELEMENT Santa ""
|- NODE_TEXT #text "\n\t\n"
и XML:
<?xml version="1.0"?>
<Santa>LF
TABLF
</Santa>
То, что они сказали вам, было правдой, с определенной точки зрения.
- строка xml, содержащая только пробелы в элементе, будет опущена при анализе
- элемент DOM, содержащий только пробел в тексте node, отобразит пробел при преобразовании в строку xml