2010-12-14 15 views
1

Ich habe eine XML-Datei, die einige Werte in Kind Element sowie in Attributen hat. Wenn ich einen Text ersetzen möchte, wenn ein bestimmter Wert übereinstimmt, wie kann ich es erreichen? Ich versuchte mit xlst:translate() Funktion. Aber ich kann diese Funktion nicht für jedes Element oder Attribut in XML verwenden. Gibt es also einen Wert zu ersetzen/zu übersetzen auf einmal?Ersetzen von Text in xml mit xslt

<?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> 

Ausgang:

<?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> 

in der Ausgabe, ersetzt Text von Kanada nach Unitedstates. Also, ohne xslt: transform() - Funktionen auf einem beliebigen Element, sollte ich in der Lage sein, Text Canada zu UnitedStates unabhängig von Level-Knoten zu ersetzen. Wo immer ich 'Canada' finde, sollte ich in der Lage sein, zu 'UnitedStates' in ganzem XML zu ersetzen. Also wie kann ich das erreichen?

+0

Können Sie bitte angeben, was Sie versuchen zu erreichen. Wenn Sie uns einen Beispielcode mit Eingabe und gewünschter Ausgabe geben, wäre dies einfacher zu beantworten. Ist es auch möglich, XSLT 2.0 zu verwenden? In diesem Fall könnte es möglich sein, ['fn: replace()'] (http://www.w3.org/TR/xpath-functions/#func-replace) –

+0

Ausgezeichnete Frage, +1. Sehen Sie sich meine Antwort für eine vollständige XSLT 1.0-Lösung an, die mehrere Rep-Ziele in einem Parameter akzeptiert und mehrere Ersetzungen in jedem Attribut- oder Textknoten durchführt. Außerdem wird der Unterschied mit einer XSLT 2.0-Lösung angegeben. –

+0

@Per T, danke, ich benutze XSLT 1.0. Die Ausgabe ist ziemlich geradlinig, Für jede Eingabe XML muss ich Text ersetzen, ohne den Elementnamen anzugeben. Daher sollte er nur dann alle untergeordneten Elemente ersetzen, wenn Text übereinstimmt. –

Antwort

4

I. XSLT 1.0 Lösung:

Diese Transformation:

<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> 

wenn auf diesem XML-Dokument angewendet:

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

erzeugt die gewünschte, richtige Ergebnis :

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

Erklärung:

  1. Die Identität Regel verwendet wird, kopieren "wie besehen" einige Knoten.

  2. Wir führen mehrere Ersetzungen, parametrisierten in my:Reps

  3. Wenn ein Textknoten oder ein Attribut keine rep-Target enthält, kopiert wird wie sie ist.

  4. Wenn ein Textknoten oder ein Attribut enthält Text (rep target) ersetzt werden, dann die Ersetzungen in der Reihenfolge, in my:Reps

  5. angegeben durchgeführt, wenn der String mehr als ein enthält String-Ziel, dann werden alle Ziele ersetzt: zuerst alle Vorkommen des ersten Wiederholungsziels, dann alle Vorkommen des zweiten Wiederholungsziels, ..., zuletzt alle Vorkommen des letzten Wiederholungsziels.

II. XSLT 2.0 Lösung:

In XSLT 2.0 kann man einfach die Standard XPath 2.0 Funktion replace() verwenden. Für mehrere Ersetzungen wäre die Lösung der oben angegebenen XSLT 1.0-Lösung jedoch immer noch sehr ähnlich.

+0

Vielen Dank, das hat wirklich geholfen !!! –

+0

+1 Große Antwort! –

+0

+1 Sehr gute Antwort. –