Étant donné un arbre XML profondément imbriqué, je veux trouver un certain élément. À ce stade, je veux envelopper X dans un nouvel élément qui est au même niveau qu'un élément supérieur. Je veux ensuite continuer avec le reste de l'arbre d'origine à partir du point après l'élément «certain».Comment diviser une structure imbriquée avec XSLT?
Par exemple, étant donné cette entrée:
<root>
<branch att="yo">
<div stuff="no">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
</branch>
</root>
Je veux trouver l'article 2 dans la < ul> (peasy facile). Je veux insérer un nouvel élément au niveau de la branche avant le point 2. Et puis je veux continuer avec l'élément 2 (en continuant ainsi les nœuds ancêtres). C'est, je veux que cette sortie:
<root>
<branch att="yo">
<div stuff="no">
<ul>
<li>Item 1</li>
</ul>
</div>
</branch>
<branch>
<div>
<p>New branch here</p>
</div>
</branch>
<branch att="yo">
<div stuff="no">
<ul>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
</branch>
</root>
J'ai un problème mal à démarrer avec cela dans le but de faire une solution généralisée . Je pense qu'il impliquera soit des modes multiples ou des clés avec le traitement des noeuds ancêtres pour trouver les noms et les attributs des noeuds. Toute aide est appréciée.
D'accord, c'est ce que j'ai jusqu'ici. Il fonctionne partiellement (par exemple, je copie des nœuds mais pas d'attributs, je copie aussi trop de nœuds mais c'est un début je pense). Ma pensée ici est que j'ai besoin d'une fonction récursive. Je commence par l'ancêtre le plus éloigné qui me concerne (branche) et pour chaque nœud enfant dont le descendant ultime est l'élément certain (li "item 2"), je copie chaque nœud et ses attributs, en l'ajoutant au nœud précédent (c'est qu'est-ce que newNewTree est pour). Et je recurai jusqu'à ce que j'atteigne l'élément certain (point 2 de li), auquel point je renvoie la variable NewNewTree, qui est mon intention pour que ce soit un arbre des éléments ancêtres droits (sans texte). Pour que cela fonctionne, je pense que ce que je dois faire est de traiter chaque nœud de la fonction à travers un remplacement de modèle d'identité qui copie le nœud et ses attributs. Mais trop fatigué pour tenter ça ce soir.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://www.example.com"
exclude-result-prefixes="xs my"
version="2.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:sequence select="$origNodesNoText" />
</xsl:template>
<xsl:variable name="ancestorElemName" select="'div'" />
<xsl:variable name="origNodesNoText">
<xsl:apply-templates select="/" mode="origNodesNoText"/>
</xsl:variable>
<xsl:template match="text()" mode="origNodesNoText"/>
<xsl:template match="li[.='Item 2']" mode="origNodesNoText">
<xsl:variable name="newTree">
<xsl:element name="{local-name(ancestor::*[local-name()=$ancestorElemName][1])}">
<xsl:for-each select="ancestor::*[local-name()=$ancestorElemName][1]/attribute::*">
<xsl:attribute name="{local-name()}" select="."/>
</xsl:for-each>
</xsl:element>
</xsl:variable>
<xsl:sequence select="my:split(ancestor::*[local-name()=$ancestorElemName][1],.,$newTree)" />
</xsl:template>
<xsl:function name="my:split">
<xsl:param name="ancestorElemNode" />
<xsl:param name="callingNode" />
<xsl:param name="newTree" />
<xsl:message>Calling my split</xsl:message>
<xsl:choose>
<xsl:when test="$ancestorElemNode ne $callingNode">
<xsl:message>Found a node to copy its name and attributes</xsl:message>
<xsl:variable name="newNewTree">
<xsl:for-each select="$newTree/node()">
<xsl:copy /> <!-- doesn't copy attribute nodes so not what we want -->
</xsl:for-each>
<xsl:element name="{local-name($ancestorElemNode)}">
<xsl:for-each select="$ancestorElemNode/attribute::*">
<xsl:attribute name="{local-name()}" select="."/>
</xsl:for-each>
</xsl:element>
</xsl:variable>
<xsl:sequence select="my:split($ancestorElemNode/child::*[descendant::*[. eq $callingNode]][1],$callingNode,$newNewTree)" />
</xsl:when>
<xsl:otherwise>
<xsl:message>Found the end point</xsl:message>
<xsl:sequence select="$newTree" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>
W ow Je vous remercie. C'est beau. Un seul problème, le @att sur la branche n'est pas copié post-banane. J'ai fait un changement et ça a marché, je ne suis pas sûr des conséquences de ce changement. (Je ne suis pas familier avec la construction <<.) Voici ce que je devais faire: – user5923
Dans ce modèle: dans le choix, je devais faire le vide quand dans ceci: –
user5923
Je n'ai pas trouvé un effet secondaire négatif à la modification de l'élément xsl: when J'ai mentionné. Merci beaucoup monsieur. – user5923