Как сохранить Empty XML-теги после XSLT - предотвратить свертывание их с <B></B> до <B/">

Скажем, у меня очень простой 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"?

Спасибо.

Ответ 1

Хорошо, так вот что сработало для меня:

<xsl:output method="html">

Ответ 2

Попробуйте следующее:

<script type="..." src="...">&#160;</script>

Ваш вывод HTML будет:

<script type="..." src="..."> </script>

&#160; предотвращает свертывание, но переводит в пустое пространство. Это работало для меня в прошлом.

Ответ 3

Нет стандартного способа, поскольку они эквивалентны; Возможно, вы найдете механизм XSLT, у которого есть опция для этого поведения, но я не знаю о нем.

Если вы передаете это третьему лицу, которое не может принимать пустые теги с использованием этого синтаксиса, вам может потребоваться выполнить пост-обработку вывода самостоятельно (или убедить третью сторону исправить их синтаксический анализ XML)

Ответ 4

Именно механизм XSLT определяет, как визуализируется XML-тег, потому что парсер не должен видеть разницы между этими двумя вариантами. Однако при выводе HTML это обычная проблема (например, для тегов <textarea> и <script>). Самое простое (но уродливое) решение состоит в том, чтобы добавить единый пробел внутри тега (это немного меняет значение тега хотя.)

Ответ 5

Это была давняя проблема, и я наконец заставил ее работать с простым решением.

Добавьте <xsl:text/>, если у вас есть пробел. Я добавил пробел в свой класс помощников.

<xsl:choose>
 <xsl:when test="$textAreaValue=' '">
   <xsl:text/>
 </xsl:when>
 <xsl:otherwise>
   <xsl:value-of select="$textAreaValue"/>
 </xsl:otherwise>
</xsl:choose>

Ответ 6

Они НЕ всегда эквивалентны. Многие браузеры не могут справиться с <script type="..." src="..." /> и хотят отдельный закрывающий тег. Я столкнулся с этой проблемой при использовании xml/xsl с PHP. Вывод "html" не сработал, я все еще ищу решение.

Ответ 7

Также должен быть другой метод (только XSLT2?): "xhtml" (см. другой поток). Это предотвратит сбой ваших тегов и не удаляет закрывающие теги из таких элементов, как <meta> .

Ответ 8

Нет. 2 синтаксически идентичны, поэтому вам не придется беспокоиться

Ответ 9

Это не должно быть проблемой, если оно есть или . Однако, если вы используете другой инструмент, который ожидает пустые теги XML как , тогда у вас есть проблема. Не очень элегантный способ сделать это будет добавлением пробела между просмотром и окончанием тегов "B" через XSLT-код.

Ответ 10

<xsl:text disable-output-escaping="yes">
<![CDATA[<div></div>]]>
</xsl:text>

Это отлично работает с классом С# XslCompiledTransform с .Net 2.0, но может очень неудачно почти нигде. Не используйте, если вы программно не выполняете transofrm; он вообще не переносится.

Ответ 11

Это 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>

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