2016-12-06 20 views
0

私たちのソフトウェア用のユーザー編集可能なXML構成ファイルがあります。このファイルは、Javaアプリケーションでアンマーシャリングされています。設定ファイル内の文字列に新しい変数を追加できるようにしたいと考えています。XSLT 2.0を使用して不明な文字列を置換する

私はこのような構造を持つXMLを持っている:

<root> 
    <variables> 
     <key1>foo</key1> 
     <key2>bar</key1> 
     ... 
     <keyn>nthbar</keyn> 
    </variables> 

    <some-tag>PlainText.${key1}.${keyn}.${key2}.MorePlainText</some-tag> 
    <other-tag>${key3}</other-tag> 
</root> 

私は知らキーの値を置き換えるために、このような何かをXSLT 2.0を使用することができることを承知している:

<xsl:variable name="key1" select="root/variables/key1/text()" /> 
<xsl:variable name="key2" select="root/variables/key1/text()" /> 
... 
<xsl:variable name="keyn" select="root/variables/key1/text()" /> 

<xsl:template match="text()"> 
    <xsl:value-of select="replace(replace(replace(., '\$\{val1\}', $key1), '\$\{val2\}', $key2), '\$\{valn\}', $keyn)" /> 
</xsl:template> 

トラブルこれはあまり柔軟ではないということです。新しいreplace()は、新しいキーが追加されるたびに既存のreplace()呼び出しをラップする必要があり、対応するxslファイルで新しい変数を宣言する必要があります。

XSLTを使用して、XMLファイルの別の場所にある文字列で$ {keyn}のようなタグを使用すると、値のようなタグを参照するのに滑らかな方法がありますか?

答えて

1

あなたのvariables/*要素を一致させるためにキーを使用することができますし、テキストノードで{$var}を見つけるためにanalyze-stringを使用することができます。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:key name="variables" match="variables/*" use="local-name()"/> 

    <xsl:variable name="main-root" select="/"/> 

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

    <xsl:template match="root/variables"/> 

    <xsl:param name="variable-pattern" as="xs:string">\$\{(\w+)\}</xsl:param> 

    <xsl:template match="text()"> 
     <xsl:analyze-string select="." regex="{$variable-pattern}"> 
      <xsl:matching-substring> 
       <xsl:value-of select="key('variables', regex-group(1), $main-root)"/> 
      </xsl:matching-substring> 
      <xsl:non-matching-substring> 
       <xsl:value-of select="."/> 
      </xsl:non-matching-substring> 
     </xsl:analyze-string> 
    </xsl:template> 

</xsl:stylesheet> 

私は一致するものが見つかった場合はエラーを発生させる方が良いでしょうと思いますが、 key('variables', regex-group(1), $main-root)には定義がありません:

<xsl:template match="text()"> 
    <xsl:analyze-string select="." regex="{$variable-pattern}"> 
     <xsl:matching-substring> 
      <xsl:variable name="var-match" select="key('variables', regex-group(1), $main-root)"/> 
      <xsl:choose> 
       <xsl:when test="$var-match"> 
        <xsl:value-of select="$var-match"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:message select="concat('No match found for $', regex-group(1))"/> 
       </xsl:otherwise> 
      </xsl:choose>   
     </xsl:matching-substring> 
     <xsl:non-matching-substring> 
      <xsl:value-of select="."/> 
     </xsl:non-matching-substring> 
    </xsl:analyze-string> 
</xsl:template> 
+0

ありがとう!私がしなければならなかった唯一の変更は、実際のルートタグにrootの名前を変更して、タグの内容が出力にコピーされていることを確認することでした - それらを必要としています;-) – circleofconfusion

+1

これは全く同等ではありません元のコードに戻します。オリジナルでは、 '$ {key1} 'を置き換えると' $ {key2}'を含む文字列が生成された場合、そのキーでさらに置き換えが行われます。 @ MartinHonnenの解では、置換えの出力はそれ以上の置換のために考慮されません。 –

関連する問題