XSLT интерпретирует теги с пробелами как пустые теги - PullRequest
2 голосов
/ 13 марта 2012

У меня есть XSLT, который преобразуется в XML с использованием System.Xml.Xsl.XslCompiledTransform. Проблема в том, что теги с пробелами преобразуются в пустые теги. Ниже приведен минимальный образец для воспроизведения проблемы.

Исходные данные:

<data>
  <content>A</content>
  <content> </content>
  <content>B</content>
</data>

Выходные данные:

<?xml version="1.0" encoding="utf-8"?>
<data>
  <content>A</content>
  <content />
  <content>B</content>
</data>

Второй тег неверен! Пространство не должно быть съедено таким образом.

И XSLT :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:preserve-space elements="content"/>
<xsl:template match="//data">
  <xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

XSLT не так? Или я должен винить .NET XSL трансформатор (я пробовал и 3.5 SP1 и 4.0)?

Пожалуйста, помогите!

Ответы [ 3 ]

2 голосов
/ 13 марта 2012

Если вы используете msxml, он имеет документированное несоответствие со спецификацией xml и по умолчанию удаляет пробелы.Вы можете либо добавить xml:space="preserve" к своему элементу, чтобы пустые места в этом файле были правильно обработаны, либо при вызове msxml через API (но не при непосредственном синтаксическом анализе xml в Internet Explorer) установить для его свойства preserveWhitespace значение true http://msdn.microsoft.com/en-us/library/windows/desktop/ms766466%28v=vs.85%29.aspx

Не имеет отношения к проблеме пробелов

<xsl:template match="//data/content">
  <xsl:element name="{title}">
    <xsl:apply-templates select="//data/content"/>
  </xsl:element>
</xsl:template>

никогда не выполняется, так как соответствующий шаблону data просто копирует весь документ, без рекурсивного применения шаблонов.Если бы он был выполнен, он бы работал бесконечно, как говорится, для каждого элемента содержимого, применяя шаблоны к каждому элементу содержимого.

ОБНОВЛЕНИЕ Если вам не нужно сохранять точное пустое пространство,просто вставив пробел, чтобы сделать его не пустым, вы можете исправить неисправный синтаксический анализ, вернув пробел обратно в таблицу стилей, сначала исправить вещи, чтобы шаблоны применялись рекурсивно, а затем иметь дополнительный шаблон для пустых элементов содержимого, делая их непустымидобавив пробел.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="*">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="content[not(node())]">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:text> </xsl:text>
  </xsl:copy>
 </xsl:template>

</xsl:stylesheet>
2 голосов
/ 13 марта 2012

Как отметил Дэвид, проблема в том, что пробелы удаляются перед тем, как попасть в XSLT.Решение при использовании .NET заключается в использовании XmlReader для чтения входного XML - этот код должен выполнить трюк:

  XslCompiledTransform transform = new XslCompiledTransform();
  transform.Load(@"c:\temp\space.xslt");
  using (XmlReader reader = XmlReader.Create(@"c:\temp\spaceSample.xml")) {
    using (XmlWriter writer = XmlWriter.Create(@"c:\temp\space.xml")) {
      transform.Transform(reader, writer);
    }
  }

, где spaceSample.xml во входном файле, space.xml - это выводspace.xslt - это преобразование.

(протестировано в .NET 4.0)

2 голосов
/ 13 марта 2012

Вам необходимо включить (на верхнем уровне):

<xsl:preserve-space elements="content"/>

Если есть несколько типов узлов, которые должны сохранять пробелы, перечислите их в атрибуте elements, разделенном пробелами. Это задокументировано здесь .

...