XSLT: déplacer le noeud d'un niveau vers le haut
je voudrais savoir comment déplacer les noeuds d'un niveau en utilisant XSLT si certaines conditions sont respectées. Pour vous donner un exemple, jetez un coup d'oeil à la source XML suivante:
<Settings>
<String [...]>
<Boolean [...]/>
</String>
</Settings>
C'est le XML que j'ai comme situation de départ. Pour être clair, les noms de noeuds "Settings", "String", "Boolean" sont des noeuds spéciaux que nous avons définis.
le problème est que les noeuds" booléens "ne sont pas autorisés à l'intérieur des noeuds" String". C'est pourquoi je dois déplacer ces noeuds "booléens" au niveau supérieur. Le le XML désiré ressemblerait à ceci:
<Settings>
<String [...]></String>
<Boolean [...]/>
</Settings>
le XSLT doit aussi fonctionner avec chaque noeud de chaîne qui a un noeud booléen frère, quelle que soit la position dans L'arborescence XML.
Jusqu'à présent j'ai appris que vous devez d'abord copier tout votre XML en utilisant une "règle d'identité" et ensuite appliquer quelques règles spéciales pour les transformations souhaitées:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<!-- Identity rule -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!-- special rules ... -->
</xsl:stylesheet>
la chose avec laquelle je suis en difficulté est la règle pour déplacer tous les noeuds "booléens" qui sont des frères de noeuds "String" un monter de niveau. Comment puis-je le faire?!?
3 réponses
Mon interprétation de l'exigence donne la solution
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="String">
<xsl:copy>
<xsl:apply-templates select="child::node()[not(self::Boolean)]"/>
</xsl:copy>
<xsl:apply-templates select="Boolean"/>
</xsl:template>
</xsl:stylesheet>
Essayez le code suivant:
<!-- copy all -->
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<!-- ignore booleans-inside-strings -->
<xsl:template match="String/Boolean" />
<!-- place the booleans-inside-strings into the settings element -->
<xsl:template match="Settings">
<xsl:copy>
<xsl:copy-of select="//String/Boolean" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
cette solution est assez similaire à celle de @Michae-Kay. Cependant, le dépassement de la règle d'identité est un peu plus précis -- seulement String
éléments qui ont vraiment un Boolean
enfant sont appariés:
<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="String[Boolean]">
<xsl:copy>
<xsl:apply-templates select="node()[not(self::Boolean)]|@*"/>
</xsl:copy>
<xsl:apply-templates select="Boolean"/>
</xsl:template>
</xsl:stylesheet>
lorsque cette transformation est appliquée au document XML suivant:
<Settings>
<String>
<Boolean />
</String>
<String/>
</Settings>
le résultat voulu et correct est produit:
<Settings>
<String/>
<Boolean/>
<String/>
</Settings>