Здесь я хочу выбрать ближайшего брата первого <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>
Обновление : ОП уточнил, что нужноРезультатом преобразования является (группировка), так что вот:
I.Решение 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>