2017-07-21 2 views
0

XML Entrée:Copier les enfants directs et leurs attributs uniquement dans 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> 

sortie souhaitée (sorte de « copie superficielle » avec seulement les éléments enfants immédiats et attributs):

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

Y at-il une autre façon (par exemple, sans pour-chacun) pour y parvenir?

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

modifier: les nœuds de texte « Valeur Y » et « Valeur Z » sont effectivement censés être le résultat. "Foo" et "Bar" ne sont toujours pas souhaités dans le résultat.

Répondre

1

Un modèle très court utilise les parent:: -axis:

<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()" /> 

sa sortie est

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

Désolé, une erreur dans la sortie désirée (voir ma question Edited). Avec votre solution, le résultat est ' Valeur XFooBar' (tous les nœuds de texte concaténés) et '' (pas de nœud de texte), mais ce que je cherche pour est '' (noeud vide, pas de texte enfants) et ' Valeur Y' (avec enfant de texte). – CoDEmanX

+0

@CoDEmanX: J'ai mis à jour ma réponse. – zx485

1

Une façon est de ne pas traiter les petits-enfants:

<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

Bonne réflexion. Si j'ajuste le dernier modèle à 'record/*/*', le résultat ressemble à ma sortie désirée (mise à jour)! Ensemble avec '' c'est parfait (il y a des éléments adjacents à recordList Je veux exclure, y compris leurs nœuds de texte). Merci! – CoDEmanX

+0

J'avais d'abord 'record/*/*', mais je l'ai changé en 'record/*/node()' car la sortie demandée à un moment donné semblait avoir 'Field3' vide. Mais l'approche est l'étape importante. –

0

Que diriez-vous simplement ne pas appliquer de modèles aux nœuds que vous ne voulez pas?

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>