2010-12-14 20 views
1

私は子要素にいくつかの値を属性にも含むXMLファイルを持っています。 特定の値が一致したときにテキストを置き換えたい場合、どのように達成できますか? xlst:translate()機能を試しました。しかし、私はこの機能をxmlの各要素や属性に対して使用することはできません。 ワンショットで値を置換/変換する方法はありますか?xsltを使用してxmlのテキストを置き換えます。

<?xml version="1.0" encoding="UTF-8"?> 
<Employee> 
<Name>Emp1</Name> 
<Age>40</Age> 
<sex>M</sex> 
<Address>Canada</Address> 
<PersonalInformation> 
    <Country>Canada</country> 
    <Street1>KO 92</Street1> 
</PersonalInformation> 
</Employee> 

出力:出力の

<?xml version="1.0" encoding="UTF-8"?> 
<Employee> 
<Name>Emp1</Name> 
<Age>40</Age> 
<sex>M</sex> 
<Address>UnitedStates</Address> 
<PersonalInformation> 
    <Country>UnitedStates</country> 
    <Street1>KO 92</Street1> 
</PersonalInformation> 
</Employee> 

は、カナダからUnitedStatesのにテキストを置き換えます。 したがって、どの要素でもxslt:transform()関数を使用することなく、レベルノードに関係なく、カナダのテキストをUnitedStatesに置き換えることができます。 これまで私は 'Canada'を見つけましたが、私はxml全体で 'UnitedStates'に代わることができます。 これをどのように達成できますか?

+0

あなたはあなたが達成しようとしていることを明記してください。入力と希望出力があるサンプルコードを私たちに与えると、これは簡単に答えることができます。また、XSLT 2.0を使用することも可能ですか?その場合、['fn:replace()'](http://www.w3.org/TR/xpath-functions/#func-replace) –

+0

優れた質問、+1を使用することができます。パラメータで複数のrep-targetsを受け入れ、任意の属性またはテキストノードで複数の置換を実行する完全なXSLT 1.0ソリューションについては、私の答えを参照してください。また、XSLT 2.0ソリューションを使用する違いが指定されています。 –

+0

@Per T、ありがとう、私はXSLT 1.0を使用しています。出力は非常に簡単です。任意の入力XMLに対して、要素名を指定せずにテキストを置き換える必要があります。テキストが一致している場合のみ、すべての子要素の置換を適用する必要があります。 –

答えて

4

I.のXSLT 1.0ソリューション:

この変換:このXMLドキュメントに適用

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 
<my:Reps> 
    <rep> 
    <old>replace this</old> 
    <new>replaced</new> 
    </rep> 
    <rep> 
    <old>cat</old> 
    <new>tiger</new> 
    </rep> 
</my:Reps> 

<xsl:variable name="vReps" select= 
    "document('')/*/my:Reps/*"/> 

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

<xsl:template match="@*"> 
    <xsl:attribute name="{name()}"> 
    <xsl:call-template name="replace"> 
    <xsl:with-param name="pText" select="."/> 
    </xsl:call-template> 
    </xsl:attribute> 
</xsl:template> 

<xsl:template match="text()" name="replace"> 
    <xsl:param name="pText" select="."/> 
    <xsl:if test="string-length($pText)"> 
    <xsl:choose> 
     <xsl:when test= 
     "not($vReps/old[contains($pText, .)])"> 
     <xsl:copy-of select="$pText"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:variable name="vthisRep" select= 
     "$vReps/old[contains($pText, .)][1] 
     "/> 

     <xsl:variable name="vNewText"> 
      <xsl:value-of 
      select="substring-before($pText, $vthisRep)"/> 
      <xsl:value-of select="$vthisRep/../new"/> 
      <xsl:value-of select= 
      "substring-after($pText, $vthisRep)"/> 
     </xsl:variable> 

     <xsl:call-template name="replace"> 
      <xsl:with-param name="pText" 
      select="$vNewText"/> 
     </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

<t> 
<a attr1="X replace this Y"> 
    <b>cat mouse replace this cat dog</b> 
</a> 
<c/> 
</t> 

を指名手配、正しい結果を生成し

<t> 
    <a attr1="X replaced Y"> 
     <b>tiger mouse replaced tiger dog</b> 
    </a> 
    <c/> 
</t> 

説明

  1. アイデンティティルールは、いくつかのノード "であるとして、" コピーするを使用しています。

  2. 我々はテキストノードまたは属性がどのREP-のターゲットが含まれていない場合、そのままコピーされmy:Reps

  3. でパラメータ
  4. 、複数の置換を行います。

  5. テキスト・ノードまたは属性がテキストを交換する(REP対象)が含まれている場合、文字列が複数含まれている場合、次いで置換をmy:Reps

  6. で指定された順序で行われる文字列ターゲットの場合、すべてのターゲットが置換されます。:最初のrepターゲットのすべての発生、次に2番目のrepターゲットのすべての発生、...、最後のrepターゲットのすべての発生。

II。 XSLT 2.0ソリューション

XSLT 2.0では、単に標準のXPath 2.0関数replace()を使用できます。しかし、複数の置換えの場合、ソリューションはまだ上記のXSLT 1.0ソリューションと非常によく似ています。

+0

本当に助けてくれてありがとう! –

+0

+1すばらしい答え! –

+0

+1非常に良い答えです。 –

関連する問題