XSLT: <xsl: strip-space> не работает - PullRequest
5 голосов
/ 16 июля 2009

В моем приложении есть фильтр сервлетов, который перехватывает все входящие запросы и пытается убрать пробелы из входящего XML и записать полученный «чистый» XML в ответ.Я использую XSLT для достижения этой цели.Пожалуйста, смотрите XSLT ниже:

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

<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="@*|node()">
<xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Однако, это не работает, как ожидалось.Результирующий XML совпадает с исходным XML (несмотря на использованиев таблице стилей.

Пожалуйста, помогите мне понять это правильно.

С уважением,
- Ашиш

Ответы [ 3 ]

17 голосов
/ 16 июля 2009

Непонятно, что вы намереваетесь получить в качестве выхода, и что вы ожидаете от xsl:strip-whitespace в первую очередь. Но следует отметить, что он не удаляет всех пробелов, а только то, что считается незначительным в соответствии с «обычными» правилами. В частности, из спецификации XSLT 1.0:

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

Так, например, это:

<foo>
  <bar>   </bar>
</foo>

будет сокращено до:

<foo><bar/></foo>

потому что у него было 3 текстовых узла только для пробелов (после <foo> и до <bar>, между <bar> и </bar> и после </bar> и до </foo>).

Обратите внимание, что, поскольку у вас есть <xsl:output indent="yes"> в вашей таблице стилей, она будет преобразована в:

<foo>
   <bar/>
<foo>

на выходе.

С другой стороны, это:

<foo>
   text1
   <bar>  text2  </bar>
   text3
</foo>

Не будет удален вообще, поскольку все содержащиеся в нем текстовые узлы не являются чисто пробельными узлами.

15 голосов
/ 16 июля 2009

Используя xslt из исходного вопроса, <xsl:template match="text()"><xsl:value-of select="normalize-space(.)"/></xsl:template> должен добиться цели.

2 голосов
/ 16 июля 2009

Добавление этого как второго ответа, потому что объяснение в первом все еще (надеюсь) достаточно информативно, чтобы сохранить его.

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

<xsl:variable name="whitespace">&#x20;&#x9;&#xD;&#xA;</xsl:variable>

<!-- Trim all whitespace at beginning of string -->
<xsl:template name="trim-start">
   <xsl:param name="text"/>
   <xsl:variable name="first-char" select="substring($text, 1, 1)" />
   <xsl:choose>
     <xsl:when test="contains($whitespace, $first-char)">
       <xsl:call-template name="trim-start">
         <xsl:with-param name="text" select="substring($text, 2)" />
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$text" />
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<!-- Trim all whitespace at end of string -->
<xsl:template name="trim-end">
   <xsl:param name="text"/>
   <xsl:variable name="last-char" select="substring($text, string-length($text), 1)" />
   <xsl:choose>
     <xsl:when test="contains($whitespace, $last-char)">
       <xsl:call-template name="trim-end">
         <xsl:with-param name="text" select="substring($text, 1, string-length($text) - 1)" />           </xsl:call-template>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="$text" />
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<xsl:template match="text()">
  <xsl:call-template name="trim-start">
    <xsl:with-param name="text">
      <xsl:call-template name="trim-end">
        <xsl:with-param name="text" select=".">
      </xsl:call-template>
    <xsl:param>
  </xsl:call-template>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...