Здесь я хочу выбрать следующего брата первого <w:p>
с помощью оператора for-each
, пока он не встретит следующий <w:p>
, имеющий свой <w:pPr><w:pStyle w:val="Heading1"/></w:pPr>
.
Это преобразование XSLT 2.0 демонстрирует один из способов его выполнения с помощью оператора XPAth 2.0 >>
:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
exclude-result-prefixes="w xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*/w:p[1]">
<xsl:variable name="vNextWP" select=
"following-sibling::w:p
[w:pPr/w:pStyle/@w:val='Heading1']
[1]
"/>
<xsl:copy-of select=
"following-sibling::w:p[$vNextWP >> .]"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
при применении к предоставленному XML-документу:
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p> <!-- Current Node -->
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>
Paragraph1
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph2
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph3
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>
Paragraph4
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph5
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>
Paragraph6
</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
выбираются и копируются в выходные данные именно нужные узлы:
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph2
</w:t>
</w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph3
</w:t>
</w:r>
</w:p>
Обновление: OP разъяснил, какой результат преобразования требуется (группировка), поэтому вот:
И. Решение XSLT 1.0:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
exclude-result-prefixes="w">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing"
match="w:p[not(w:pPr/w:pStyle/@w:val = 'Heading1')]
|
w:tbl"
use="generate-id(preceding-sibling::w:p
[w:pPr/w:pStyle/@w:val = 'Heading1'][1])
"/>
<xsl:template match="/*">
<Document>
<xsl:apply-templates/>
</Document>
</xsl:template>
<xsl:template match=
"w:p[w:pPr/w:pStyle/@w:val = 'Heading1']">
<Heading1>
<xsl:apply-templates mode="inGroup" select=
". | key('kFollowing', generate-id())"/>
</Heading1>
</xsl:template>
<xsl:template match="*" mode="inGroup">
<paragraph>
<xsl:value-of select="normalize-space(.//w:t)"/>
</paragraph>
</xsl:template>
<xsl:template match="w:body/*" priority="-1"/>
</xsl:stylesheet>
когда это преобразование применяется к вновь предоставленному XML-документу:
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p> <!-- Current Node -->
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>
Paragraph1
</w:t>
</w:r>
</w:p>
<w:tbl>
<w:t>table info
</w:t>
</w:tbl>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph2
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph3
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>
Paragraph4
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>
Paragraph5
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>
Paragraph6
</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
получен желаемый правильный результат:
<Document>
<Heading1>
<paragraph>Paragraph1</paragraph>
<paragraph>table info</paragraph>
<paragraph>Paragraph2</paragraph>
<paragraph>Paragraph3</paragraph>
</Heading1>
<Heading1>
<paragraph>Paragraph4</paragraph>
<paragraph>Paragraph5</paragraph>
</Heading1>
<Heading1>
<paragraph>Paragraph6</paragraph>
</Heading1>
</Document>
II. Решение XSLT 2.0:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
exclude-result-prefixes="w" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<Document>
<xsl:for-each-group
select="*/*"
group-starting-with="w:p[w:pPr/w:pStyle/@w:val = 'Heading1']">
<Heading1>
<xsl:for-each select="current-group()//w:t">
<paragraph>
<xsl:sequence select="normalize-space(.)"/>
</paragraph>
</xsl:for-each>
</Heading1>
</xsl:for-each-group>
</Document>
</xsl:template>
</xsl:stylesheet>
когда это преобразование XSLT 2.0 применяется к тому же XML-документу (см. выше), получается тот же желаемый правильный результат:
<Document>
<Heading1>
<paragraph>Paragraph1</paragraph>
<paragraph>table info</paragraph>
<paragraph>Paragraph2</paragraph>
<paragraph>Paragraph3</paragraph>
</Heading1>
<Heading1>
<paragraph>Paragraph4</paragraph>
<paragraph>Paragraph5</paragraph>
</Heading1>
<Heading1>
<paragraph>Paragraph6</paragraph>
</Heading1>
</Document>
person
Dimitre Novatchev
schedule
28.12.2011