XSLT / XPath: Selecionando um comentário anterior
-
18-09-2019 - |
Pergunta
Eu tenho XML no seguinte formato que quero reformatar:
<blocks>
<!-- === apples === -->
<block name="block1">
...
</block>
<!-- === bananas === -->
<block name="block2">
...
</block>
<!-- === oranges === -->
<block name="block3">
...
</block>
</blocks>
Meu problema é que não consigo descobrir como selecionar os comentários acima de cada tag de bloco. Eu tenho o seguinte XSL:
<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>
A saída que estou tentando é:
=== Apples ===
Bloco 1
=== bananas ===
Block2
=== LANGES ===
Bloco3
Mas o melhor que posso obter é:
=== Apples ===
=== bananas ===
=== LANGES ===
Bloco 1
=== Apples ===
=== bananas ===
=== LANGES ===
Block2
=== Apples ===
=== bananas ===
=== LANGES ===
Bloco3
Estou usando o PHP se isso faz alguma diferença.
Solução
Você pode aplicar os modelos para comentários também nos seus primeiros templos de aplicação em vez do segundo, para que isso aconteça em ordem - também, essa solução depende da ordem dos dados no XML da fonte.
<xsl:template match="//blocks">
<xsl:apply-templates select="block | comment()" />
</xsl:template>
PS:- Você pode evitar o uso de "//" em suas expressões, pois pode não ser o ideal.
EDITAR Folha de estilo completa
<?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>
Adicione a seguinte instrução Se você deseja linhas de novo, depois de imprimir o valor no bloco e no comentário.
<xsl:text> </xsl:text>
Outras dicas
Sua folha de estilo é um pouco complicada.
Você deve experimentar a folha de estilo abaixo e descobrirá que ela corresponde à saída que deseja!
<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>
Esse código sempre corresponde a 1 ou 0 comentários que começam logo antes da tag de bloco atual.