2017-07-21 2 views
0

XML-Input-:Kopiere direkte Kinder und ihre Attribute nur in XSLT 1.0?

<root> 
    <recordList> 
    <record priref="1"> 
     <Group attr="val"> 
     <Field1>Value X</Field1> 
     <Field2> 
      <value lang="en-US">Foo</value> 
      <value lang="de-DE">Bar</value> 
     </Field2> 
     </Group> 
     <Field3 attr="val">Value Y</Field3> 
    </record> 
    <record priref="2"> 
     <Field3 attr="val">Value Z</Field3> 
    </record> 
    </recordList> 
</root> 

gewünschte Ausgabe (eine Art "flache Kopie" nur mit den unmittelbar untergeordneten Elemente und Attribute):

<root> 
    <record priref="1"> 
    <Group attr="val" /> 
    <Field3 attr="val">Value Y</Field3> 
    </record> 
    <record priref="2"> 
    <Field3 attr="val">Value Z</Field3> 
    </record> 
</root> 

Gibt es eine andere Art und Weise (zB ohne for-each) um das zu erreichen?

<xsl:template match="/"> 
    <root> 
    <xsl:apply-templates select="root/recordList/record" /> 
    </root> 
</xsl:template> 

<xsl:template match="record"> 
    <xsl:copy> 
    <xsl:copy-of select="@*"/> 
    <xsl:for-each select="*"> 
     <xsl:copy> 
     <xsl:copy-of select="@* | text()"/> 
     </xsl:copy> 
    </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

edit: die Textknoten „Wert Y“ und „Wert Z“ sollte eigentlich im Ergebnis. "Foo" und "Bar" sind im Ergebnis immer noch nicht erwünscht.

Antwort

1

Eine sehr kurze Vorlage verwendet die parent:: -Achse:

<xsl:template match="root|record|*[parent::record]|*[parent::record]/text()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="text()" /> 

Es ist Ausgang

<?xml version="1.0"?> 
<root> 
    <record priref="1"> 
    <Group attr="val"> 
    </Group> 
    <Field3 attr="val">Value Y</Field3></record> 
    <record priref="2"> 
    <Field3 attr="val">Value Z</Field3> 
    </record> 
</root> 
+0

Leider gab es einen Fehler in der gewünschten Ausgabe (meine editierte Frage). Mit Ihrer Lösung ist das Ergebnis ' Wert XFooBar' (alle Textknoten verkettet) und '' (kein Textknoten), aber was ich suche für ist '' (leerer Knoten, kein Text untergeordnet) und ' Wert Y' (mit Text untergeordnet). – CoDEmanX

+0

@CoDEmanX: Ich habe meine Antwort aktualisiert. – zx485

1

Eine Möglichkeit ist, keine Enkelkinder verarbeiten:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

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

    <xsl:template match="recordList"> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="record/*/node()"/> 
</xsl:transform> 
+0

Gutes Denken. Wenn ich die letzte Vorlage an 'record/*/*' anpasse, sieht das Ergebnis wie meine (aktualisierte) gewünschte Ausgabe aus! Zusammen mit '' es ist perfekt (es gibt Elemente neben recordList, die Ich möchte ausschließen, einschließlich ihrer Textknoten). Vielen Dank! – CoDEmanX

+0

Ich hatte die 'record/*/*' zuerst, aber dann änderte es in 'record/*/node()' als die angeforderte Ausgabe zu irgendeinem Zeitpunkt leer zu sein schien 'Field3'. Aber der Ansatz ist der wichtige Schritt. –

0

Wie wäre es einfach Schablonen nicht auf Knoten anwenden, die Sie nicht möchten?

XSLT 1,0

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

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

<xsl:template match="recordList"> 
    <xsl:apply-templates/> 
</xsl:template> 

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

</xsl:stylesheet> 
Verwandte Themen