2010-07-05 3 views
1

У меня, похоже, проблема с методом перевода Xalan. У меня есть следующий код:Xalan (XSLT) translate method перевод больше, чем он должен

translate(translate(string(name),'<sup>',''),'</sup>','')

Это используется для удаления <sup> и </sup> из строки (имя). К сожалению, когда я это делаю, он, похоже, удаляет s, u и p из имен. Так как имена sony Braiva <sup>tm</sup> стать ony bravia tm

Спасибо вам за помощь заранее :)

+1

Хороший вопрос (+1). См. Мой ответ для объяснения, а также два решения XSLT 1.0 и одно решение XSLT 2.0. –

ответ

5

Потому что вы сказали, что перевод() функция успешно удаления <sup> и </sup>, я предполагаю, что <sup> не является элементом в XML-документ, но кодируется как текст.

перевод() функция определена для замены отдельных символов и, как правило, не подходит для замены строки, когда длина строки больше 1.

можно написать и использовать общую замену строки рекурсивный шаблон/функция в XSLT.

Программисты XSLT 2.0 могут использовать стандартную функцию XPath 2.0 replace().

В вашем конкретном случае даже это это может быть достаточно:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="text()"> 
    <xsl:variable name="vPart1" select= 
    "substring-before(., '&lt;sup>')"/> 

    <xsl:value-of select="$vPart1"/> 

    <xsl:variable name="vPart2" select= 
    "substring-before(substring-after(., '&lt;sup>'), 
        '&lt;/sup>' 
        )"/> 

    <xsl:value-of select="$vPart2"/> 

    <xsl:variable name="vPart3" select= 
    "substring-after(., '&lt;/sup>')"/> 

    <xsl:value-of select="$vPart3"/> 
</xsl:template> 
</xsl:stylesheet> 

Когда это преобразование применяется на следующий документ XML:

<name> 
<![CDATA[sony Braiva <sup>tm</sup> xxx]]> 
</name> 

разыскиваемый результат производства:

<name> 
sony Braiva tm xxx 
</name> 

Кроме того, здесь полномасштабный рекурсивное решение шаблона:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="text()"> 
    <xsl:variable name="vFirstReplacement"> 
     <xsl:call-template name="replace"> 
     <xsl:with-param name="pText" select="."/> 
     <xsl:with-param name="pPattern" 
     select="'&lt;sup>'"/> 
     <xsl:with-param name="pReplacement" select="''"/> 
     </xsl:call-template> 
    </xsl:variable> 

    <xsl:call-template name="replace"> 
    <xsl:with-param name="pText" 
     select="$vFirstReplacement"/> 
    <xsl:with-param name="pPattern" 
    select="'&lt;/sup>'"/> 
    <xsl:with-param name="pReplacement" select="''"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="replace"> 
    <xsl:param name="pText"/> 
    <xsl:param name="pPattern"/> 
    <xsl:param name="pReplacement"/> 

    <xsl:choose> 
    <xsl:when test="not(contains($pText, $pPattern))"> 
    <xsl:value-of select="$pText"/> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:value-of select= 
     "substring-before($pText, $pPattern)"/> 

    <xsl:value-of select="$pReplacement"/> 

    <xsl:call-template name="replace"> 
     <xsl:with-param name="pText" select= 
     "substring-after($pText, $pPattern)"/> 
     <xsl:with-param name="pPattern" 
      select="$pPattern"/> 
     <xsl:with-param name="pReplacement" 
      select="$pReplacement"/> 
    </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

Когда это преобразование применяется на этот XML-документ:

<name> 
<![CDATA[sony Braiva <sup>tm</sup> xxx]]> 
</name> 

разыскиваемый, правильный результат :

<name> 
sony Braiva tm xxx 
</name> 

Наконец, здесь XSLT 2.0 решение:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="text()"> 
    <xsl:value-of select= 
    "replace(
      replace(., '&lt;sup>', ''), 
      '&lt;/sup>', 
      '' 
      ) 
    "/> 
</xsl:template> 
</xsl:stylesheet> 
+0

Спасибо. Это помогает! Вау ... серьезно из слов. Большое спасибо. – Bilzac

1

Т.Л., версия др: Не манипулировать HTML или XML в виде строк, если возможно, вы можете избежать этого. Сделайте это в XSLT.

Я предполагаю, что у вас есть какой-то элемент содержит что-то вроде

<name>Sony Braiva <sup>tm</sup></name> 

Так что, похоже, у вас есть анализируемый документ XML уже в XSLT. Затем вы поворачиваетесь и пытаетесь использовать строковые манипуляции, чтобы вытащить некоторые теги. Это плохая идея; см. this question о совпадающих тегах. XSLT именно для такого рода манипуляций, поэтому используйте его! (Если мое предположение неверно и что tm сущ. Или в секции CDATA или что-то другое, я думаю.)

Итак, во-первых. Если вы хотите полосы все теги из названия, оставив только текст, вы можете сделать

<xsl:value-of select="name" /> 

который дал бы:

Sony Braiva tm 

Если, с другой стороны, вы хотите разделите все теги sup и их содержимое, вы сначала в другом месте определите шаблон, соответствующий sup (и сделайте то же самое с любым, что вы хотите вырвать, например, теги скриптов, теги img, что угодно):

<xsl:template match="sup" /> <!-- replace sup with nothing --> 

И тогда вы можете применить

<xsl:apply-templates select="name" /> 

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

<xsl:template match="sup" mode="mangle-name"> 
    <xsl:if test="'tm' = string(.)"> 
    &#8482; 
    </xsl:if> 
</xsl:template> 

<!-- Later, somewhere else: --> 
<xsl:apply-templates select="name" mode="mangle-name" /> 

Отказ от всего этого: Это стандарт XSLT (возможно 1,0 даже), но я только попробовал его в онлайн-саксонской синтаксический анализатор, а не в Xalan.

+0

благодарит за ответ – Bilzac

 Смежные вопросы

  • Нет связанных вопросов^_^