XSLT / XPath: Sélection d'un commentaire précédent
-
18-09-2019 - |
Question
Je XML dans le format suivant que je veux reformater:
<blocks>
<!-- === apples === -->
<block name="block1">
...
</block>
<!-- === bananas === -->
<block name="block2">
...
</block>
<!-- === oranges === -->
<block name="block3">
...
</block>
</blocks>
Mon problème est que je ne peux pas comprendre comment sélectionner les commentaires ci-dessus chaque balise de bloc. Je le XSL suivant:
<xsl:template match="//blocks">
<xsl:apply-templates select="block" />
</xsl:template>
<xsl:template match="block">
<xsl:apply-templates select="../comment()[following-sibling::block[@name = ./@name]]" />
<xsl:value-of select="./@name" />
</xsl:template>
<xsl:template match="comment()[following-sibling::block]">
<xsl:value-of select="."></xsl:value-of>
</xsl:template>
La sortie que je suis en train de est:
=== === pommes
block1
=== === bananes
block2
=== oranges ===
Bloc 3
Mais le mieux que je peux obtenir est:
=== === pommes
=== === bananes
=== oranges ===
block1
=== === pommes
=== === bananes
=== oranges ===
block2
=== === pommes
=== === bananes
=== oranges ===
Bloc 3
J'utilise PHP si cela fait une différence.
La solution
Vous pouvez appliquer les modèles pour les commentaires aussi dans vos premiers apply-templates au lieu de la seconde, de sorte qu'il se passe dans l'ordre - En outre, cette solution dépend de l'ordre des données dans le fichier XML source ..
<xsl:template match="//blocks">
<xsl:apply-templates select="block | comment()" />
</xsl:template>
PS: -. Vous pourriez éviter d'utiliser "//" dans vos expressions comme il peut être non-optimale
[EDIT] Complete Stylesheet
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//blocks">
<xsl:apply-templates select="block | comment()"/>
</xsl:template>
<xsl:template match="block">
<xsl:value-of select="./@name"/>
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Ajoutez l'instruction suivante si vous voulez des nouvelles lignes, après avoir imprimé la valeur à la fois le bloc et le commentaire.
<xsl:text> </xsl:text>
Autres conseils
Votre feuille de style est un peu trop compliqué.
Vous devriez essayer la feuille de style ci-dessous et vous trouverez qu'il correspond à la sortie que vous voulez!
<xsl:template match="//blocks">
<xsl:apply-templates select="block" />
</xsl:template>
<xsl:template match="block">
<xsl:apply-templates select="preceding-sibling::comment()[1]" />
<xsl:value-of select="./@name" />
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="."></xsl:value-of>
</xsl:template>
Ce code correspond toujours à 1 ou 0 commentaires qui commencent juste avant la balise de bloc en cours.