2012-09-18 15 views
5

Ich habe eine XSLT erstellt und ich frage mich, wie es möglich ist, alle Knoten zwischen einem Satz von Tags zu kopieren und ein weiteres Tag am unteren Rand hinzuzufügen. Ich habe das XSLT erstellt, das über die gesamte Logik verfügt, um zu bestimmen, welches Tag hinzugefügt werden soll und wie es aufgerufen werden soll. Das Problem, das ich jetzt bekomme, ist, dass ich nicht alle anderen Tags auch kopieren kann. Im Folgenden sind die Dateien in Frage:XSLT - Kopieren Sie alle anderen Knoten, fügen Sie einen neuen Knoten hinzu

XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:template match="/csvImportSchema"> 
     <csvImportSchema> 
      <xsl:for-each select="payload"> 
       <payload> 
        <xsl:copy-of select="@*"/> 
        <xsl:variable name="ean"> 
         <xsl:value-of select="ean"/> 
        </xsl:variable> 
        <xsl:for-each select="../product"> 
         <xsl:if test="ean = $ean"> 
          <productId><xsl:value-of select="article"/></productId> 
         </xsl:if> 
        </xsl:for-each> 
       </payload> 
      </xsl:for-each> 
     </csvImportSchema> 
    </xsl:template> 

</xsl:stylesheet> 

INPUT

<?xml version="1.0" encoding="UTF-8"?> 
<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId/> 
    </payload> 
    <product> 
     <article>722619</article> 
     <ean>1111111111</ean> 
    </product> 
</csvImportSchema> 

STROMAUSGANG

<?xml version="1.0" encoding="utf-8"?> 
<csvImportSchema> 
    <payload> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

SOLL OUTPUT

<?xml version="1.0" encoding="UTF-8"?> 
<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

Antwort

7

Diese kurze und einfache Transformation:

<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="productId"> 
    <productId> 
    <xsl:value-of select="../../product/article"/> 
    </productId> 
</xsl:template> 
<xsl:template match="product"/> 
</xsl:stylesheet> 

wenn auf dem mitgelieferten XML-Dokument angewandt:

<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId/> 
    </payload> 
    <product> 
     <article>722619</article> 
     <ean>1111111111</ean> 
    </product> 
</csvImportSchema> 

erzeugt das gewünschte, korrekte Ergebnis:

<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

Erläuterung:

  1. Die identity rule copies "wie sie ist" jeder Knoten, für den es zur Ausführung ausgewählt wird.

  2. Eine überschreibende Vorlage, die zu product passt, löscht dieses Element aus der Ausgabe (durch seinen leeren Körper).

  3. Eine andere überschreibende Vorlage entspricht productId und generiert dieses Element mit einem Textknoten Kind aus product/article.

1

es so einfach sein sollte Ihre Nutzlast xsl:copy-of select="@*"/ zu

<xsl:copy-of select="*[local-name() != 'productId'] | @*"/> 

heißt das Ändern kopieren alles, außer productId, weil Sie diese manuell aufbauen.

Dies gibt die Ausgabe, die Sie

<?xml version="1.0" encoding="utf-8"?> 
<csvImportSchema> 
    <payload> 
    <test>1</test> 
    <test2>2</test2> 
    <test3>3</test3> 
    <ean>1111111111</ean> 
    <productId>722619</productId> 
    </payload> 
</csvImportSchema> 
1

Dieses XSLT sollte die Arbeit machen und verwendet viel mehr COPY-Tags und Vorlagen benötigt haben. Vielleicht mache nicht alles in einer xsl: template (meiner Meinung nach).

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:template match="/csvImportSchema"> 
     <xsl:copy> 
      <xsl:apply-templates select="*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/payload/productId"> 
     <xsl:variable name="ean"> 
      <xsl:value-of select="../ean"/> 
     </xsl:variable> 
     <xsl:for-each select="../../product"> 
      <xsl:if test="ean = $ean"> 
       <productId><xsl:value-of select="article"/></productId> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/product"> 
     <!-- do not copy --> 
    </xsl:template> 

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

Eine Beobachtung auf Ihrem Code. Diese Mitteilung nicht mehr verwenden:

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

, wenn Sie dies schreiben könnte:

<xsl:variable name="ean" select="../ean"/> 

nicht nur ausführliche ist es, es ist auch unglaublich ineffizient: Statt $ ean zu einem bestehenden Knoten zu binden, Sie extrahieren der Zeichenfolgenwert eines vorhandenen Knotens, der einen Textknoten mit diesem Zeichenfolgenwert bildet, einen neuen XML-Dokumentbaum erstellt und diesen Textknoten zum Inhalt dieses neuen Dokuments hinzufügt. (Ich habe einmal ein Stylesheet bekommen, das 3-mal schneller läuft, indem dieses schreckliche Konstrukt eliminiert wird.)

+0

Danke. Das werde ich mir merken. – MMKD

Verwandte Themen