2017-01-19 3 views
0

Я хочу получить первый заголовок (h1) перед таблицей в docx.XSLT: найдите первый элемент над выбранным элементом

я могу получить все заголовки с:

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

и я могу получить все таблицы

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

Но Unfortunetly процессор не принимает

<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> 

Вот уменьшенная XML-файл, извлеченный из docx: http://pastebin.com/KbUyzRVv Я хочу что-то подобное е, что в результате:

<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> 

Благодаря Даниэлю Хейли я смог найти решение этой проблемы. Я отправлю его здесь, поэтому он не зависит от пастебина, который я публикую ниже.

<?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

Всегда указать, можно ли воспользоваться XSLT 2.0. –

+0

Извините, это мой первый подход сделать что-то с XSLT. Это также прототип, поэтому я думаю, что пока есть не коммерческий процессор, версия не имеет значения. – froehli

ответ

1

Трудно ответить без Minimal, Complete, and Verifiable example, но попробуйте это:

<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

Спасибо за ваш ответ, я думаю, что он близок к решению. Ваше заявление находит тот же заголовок, но не первый выше таблицы. Я добавил pastebin с моим test-xml. Текущий xsl находится здесь: http://pastebin.com/M3kDmf1V – froehli

+1

@froehli - XSLT в вашем pastebin отсутствует самая важная часть; вам нужно обернуть все в 'select' in'() [1] '(полный выбор:' select = "(предшествующий :: w: p [w: pPr/w: pStyle [@w: val = 'berschrift1' ]]) [1] "'). –

+0

Здесь массив содержит два элемента для каждой таблицы. С [1] первый выбирается все время. Но заголовок должен измениться. Таким образом, ни с [1], ни без я получаю правильный заголовок. Я попробовал что-то, что, кажется, работает здесь: http://pastebin.com/ZnXy11NP – froehli

1

Предполагая, что вы можете использовать XSLT 2.0 (и большинство людей могут, в настоящее время), я нахожу полезный метод здесь, чтобы иметь глобальная переменная, которая выбирает все соответствующие узлы:

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

и затем использовать эту переменную в правиле шаблона:

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

В XSLT 3.0 вы можете уменьшить это

<xsl:template match="$special"/> 
Смежные вопросы