Ответ 1
Хорошо, так вот что сработало для меня:
<xsl:output method="html">
Скажем, у меня очень простой XML с пустым тегом 'B':
<Root>
<A>foo</A>
<B></B>
<C>bar</C>
</Root>
В настоящее время я использую XSLT для удаления нескольких тегов, например "C":
<?xml version="1.0" ?>
<xsl:stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no" encoding="utf-8" omit-xml-declaration="yes" />
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="C" />
</xsl:stylesheet>
До сих пор ОК, но проблема в том, что я получаю такой вывод:
<Root>
<A>foo</A>
<B/>
</Root>
когда я действительно хочу:
<Root>
<A>foo</A>
<B></B>
</Root>
Есть ли способ предотвратить свертывание "B"?
Спасибо.
Хорошо, так вот что сработало для меня:
<xsl:output method="html">
Попробуйте следующее:
<script type="..." src="..."> </script>
Ваш вывод HTML будет:
<script type="..." src="..."> </script>
 
предотвращает свертывание, но переводит в пустое пространство. Это работало для меня в прошлом.
Нет стандартного способа, поскольку они эквивалентны; Возможно, вы найдете механизм XSLT, у которого есть опция для этого поведения, но я не знаю о нем.
Если вы передаете это третьему лицу, которое не может принимать пустые теги с использованием этого синтаксиса, вам может потребоваться выполнить пост-обработку вывода самостоятельно (или убедить третью сторону исправить их синтаксический анализ XML)
Именно механизм XSLT определяет, как визуализируется XML-тег, потому что парсер не должен видеть разницы между этими двумя вариантами. Однако при выводе HTML это обычная проблема (например, для тегов <textarea>
и <script>
). Самое простое (но уродливое) решение состоит в том, чтобы добавить единый пробел внутри тега (это немного меняет значение тега хотя.)
Это была давняя проблема, и я наконец заставил ее работать с простым решением.
Добавьте <xsl:text/>
, если у вас есть пробел. Я добавил пробел в свой класс помощников.
<xsl:choose>
<xsl:when test="$textAreaValue=' '">
<xsl:text/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$textAreaValue"/>
</xsl:otherwise>
</xsl:choose>
Они НЕ всегда эквивалентны. Многие браузеры не могут справиться с <script type="..." src="..." />
и хотят отдельный закрывающий тег. Я столкнулся с этой проблемой при использовании xml/xsl с PHP. Вывод "html" не сработал, я все еще ищу решение.
Также должен быть другой метод (только XSLT2?): "xhtml" (см. другой поток). Это предотвратит сбой ваших тегов и не удаляет закрывающие теги из таких элементов, как <meta> .
Нет. 2 синтаксически идентичны, поэтому вам не придется беспокоиться
Это не должно быть проблемой, если оно есть или . Однако, если вы используете другой инструмент, который ожидает пустые теги XML как , тогда у вас есть проблема. Не очень элегантный способ сделать это будет добавлением пробела между просмотром и окончанием тегов "B" через XSLT-код.
<xsl:text disable-output-escaping="yes">
<![CDATA[<div></div>]]>
</xsl:text>
Это отлично работает с классом С# XslCompiledTransform
с .Net 2.0, но может очень неудачно почти нигде. Не используйте, если вы программно не выполняете transofrm; он вообще не переносится.
Это 7 лет спустя, но для будущих читателей я опишу здесь тенденцию и предлагаю фактическое решение первоначального вопроса. Решение, которое не изменяет оригинал с пробелами или директивой вывода.
Идея состояла в том, чтобы использовать пустую переменную, чтобы обмануть парсер.
Если вы только хотите сделать это только для одного тега B, моя первая мысль заключалась в том, чтобы использовать что-то вроде этого, чтобы прикрепить фиктивную переменную.
<xsl:variable name="dummyempty" select="''"/>
<xsl:template match="B">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:value-of select="concat(., $dummyempty)"/>
</xsl:copy>
</xsl:template>
Но я обнаружил, что на самом деле даже фиктивная переменная не нужна. Эти сохраненные пустые теги, по крайней мере, при тестировании с помощью xsltproc
в linux:
<xsl:template match="B">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
Для более общего решения для обработки ВСЕХ пустых тегов попробуйте следующее:
<xsl:variable name="dummyempty" select="''"/>
<xsl:template match="*[. = '']">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
<xsl:value-of select="$dummyempty"/>
</xsl:copy>
</xsl:template>
Опять же, в зависимости от того, насколько разумным является ваш парсер, вам может даже не понадобиться фиктивная переменная.