1

Xalan の翻訳方法に問題があるようです。次のコードがあります。

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

これは、string(name) から削除するため<sup>に使用されます。</sup>残念ながら、それを行うと、名前から s、u、および p も削除されるようです。のような名前にsony Braiva <sup>tm</sup>なるony bravia tm

事前に助けてくれてありがとう:)

4

2 に答える 2

5

<sup>translate() 関数で と が正常に削除されているとおっしゃっていたので、 は XML ドキュメントの要素ではなく、テキストとしてエンコードされていると</sup>想定しています。<sup>

translate() 関数は、個々の文字を置換するように定義されており、通常、文字列の長さが 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>
于 2010-07-05T19:25:09.533 に答える
1

tl;dr バージョン:回避できる場合は、html または xml を文字列として操作しないでください。XSLTで行います。

あなたが持っているのは、いくつかの要素に次のようなものが含まれていると仮定しています

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

したがって、解析済みの XML ドキュメントが既に XSLT に含まれているように見えます。次に、向きを変えて、文字列操作を使用していくつかのタグを引き出そうとしています。それは悪い考えです。タグの一致に関するこの質問を参照してください。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 を適切な Unicode シンボルに置き換えることもできます。これを別のモードに配置し、そのモードを使用して他のすべてのタグを削除することをお勧めします。

<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 でも) ですが、私はオンラインの Saxon パーサーでのみ試しましたが、Xalan では試していません。

于 2010-07-05T19:39:54.287 に答える