2017-01-19 1 views
0

Je souhaite obtenir le premier en-tête (h1) avant une table dans un docx.XSLT: recherche du premier élément au-dessus de l'élément sélectionné

Je peux obtenir toutes les rubriques avec:

<xsl:template match="w:p[w:pPr/w:pStyle[@w:val='berschrift1']]"> 
    <p> 
     <context> 
      <xsl:value-of select="." /> 
     </context> 
    </p> 
</xsl:template> 

et je peux aussi obtenir toutes les tables

<xsl:template match="w:tbl"> 
    <p> 
    <table> 
     <xsl:value-of select="." /> 
    </table> 
    </p> 
</xsl:template> 

Mais unfortunetly le processeur n'accepte pas

<xsl:template match="w:tbl/preceding-sibling::w:p[w:pPr/w:pStyle[@w:val='berschrift1']]"> 
    <p> 
    <table> 
     <xsl:value-of select="." /> 
    </table> 
    </p> 
</xsl:template> 

Voici un réduit Fichier XML extrait d'un docx: http://pastebin.com/KbUyzRVv Je veux quelque chose lik e en conséquence:

<context>Let’s get it on</context> <- my heading 
<table>data</table> 

<context>Let’s get it on</context> <- my heading 
<table>data</table> 

<context>We’re in the middle of something</context> <- my heading 
<table>data</table> 

Grâce à Daniel Haley, j'ai pu trouver une solution à ce problème. Je l'afficherai ici, donc il est indépendant du pastebin que je postet ci-dessous.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    xmlns:v="urn:schemas-microsoft-com:vml" exclude-result-prefixes="xsl w v"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="w:tbl"> 
      <context> 
       <xsl:value-of select="(preceding-sibling::w:p[w:pPr/w:pStyle[@w:val = 'berschrift1']])[last()]"/> 
      </context> 
      <table> 
       <xsl:value-of select="."/> 
      </table> 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 
+1

toujours indiquer si vous pouvez profiter de XSLT 2.0. –

+0

Désolé, c'est ma première approche pour faire quelque chose avec XSLT. C'est aussi un prototype, donc je pense que tant qu'il y a des processeurs non commerciaux, la version n'a pas d'importance. – froehli

Répondre

1

Difficile de répondre sans Minimal, Complete, and Verifiable example, mais essayez ceci:

<xsl:template match="w:tbl"> 
    <p> 
    <table> 
     <xsl:value-of select="(preceding::w:p[w:pPr/w:pStyle[@w:val='berschrift1']])[last()]"/> 
    </table> 
    </p> 
</xsl:template> 
+0

Merci pour votre réponse, je pense que c'est proche d'une solution. Votre déclaration trouve le même en-tête, mais pas le premier au-dessus de la table. J'ai ajouté un pastebin avec mon test-xml dedans. Le xsl actuel est ici: http://pastebin.com/M3kDmf1V – froehli

+1

@froehli - Le XSLT de votre pastebin manque la pièce la plus importante; vous devez envelopper tout dans 'select' dans'() [1] '(sélection complète:' select = "(précédant :: w: p [w: pPr/w: pStyle [@w: val = 'berschrift1' ]]) [1] "'). –

+0

Le tableau contient deux éléments pour chaque table. Avec [1] le premier est choisi tout le temps. Mais le titre doit changer. Donc, ni avec [1] ni sans obtenir le bon titre. J'ai essayé quelque chose qui semble fonctionner ici: http://pastebin.com/ZnXy11NP – froehli

1

En supposant que vous pouvez utiliser XSLT 2.0 (et la plupart des gens peuvent, de nos jours), je trouve une technique utile ici est d'avoir un variable globale qui sélectionne tous les nœuds concernés:

<xsl:variable name="special" 
    select="//w:tbl/preceding-sibling::w:p[w:pPr/w:pStyle[@w:val='berschrift1']][1]"/> 

puis utiliser cette variable dans une règle de modèle:

<xsl:template match="w:p[. intersect $special]"/> 

Dans XSLT 3.0, vous pouvez réduire à

<xsl:template match="$special"/>