Просто используйте это выражение XPath 1.0 :
/*/*/w:p[not(substring-after(@pStyle,'Heading')
>=
substring-after(preceding-sibling::*[1]/@pStyle,'Heading')
)
]
Соответствующее выражение XPath 2.0, выбирающее тот же набор элементов: :
/*/*/w:p[1]
|
/*/*/w:p[position() ge 2]
[xs:integer(substring-after(@pStyle,'Heading'))
lt
xs:integer(substring-after(preceding-sibling::*[1]/@pStyle,'Heading'))
]
Если вы используете XSLT 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="Undefined!!!">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"w:p[xs:integer(substring-after(@pStyle,'Heading'))
ge
xs:integer(substring-after(preceding-sibling::*[1]/@pStyle,'Heading'))
]"/>
</xsl:stylesheet>
при применении к предоставленному документу XML (исправлено, чтобы быть правильно сформированным):
<w:document xmlns:w="Undefined!!!">
<w:body>
<w:p pStyle="Heading1">Para1</w:p>
<w:p pStyle="Heading2">Para2</w:p>
<w:p pStyle="Heading3">Para3</w:p>
<w:p pStyle="Heading4">Para4</w:p>
<w:p pStyle="Heading1">Para5</w:p>
<w:p pStyle="Heading3">Para6</w:p>
<w:p pStyle="Heading4">Para7</w:p>
<w:p pStyle="Heading2">Para8</w:p>
<w:p pStyle="Heading3">Para9</w:p>
<w:p pStyle="Heading1">Para10</w:p>
</w:body>
</w:document>
желаемый, правильный результат выдается :
<w:document xmlns:w="Undefined!!!">
<w:body>
<w:p pStyle="Heading1">Para1</w:p>
<w:p pStyle="Heading1">Para5</w:p>
<w:p pStyle="Heading2">Para8</w:p>
<w:p pStyle="Heading1">Para10</w:p>
</w:body>
</w:document>
Соответствующее решение XSLT 1.0 с переопределением правила идентификации немного проще из-за отсутствия строгой типизации в XPath 1.0:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="Undefined!!!">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"w:p[substring-after(@pStyle,'Heading')
>=
substring-after(preceding-sibling::*[1]/@pStyle,'Heading')
]"/>
</xsl:stylesheet>
Или вы можете просто использовать выражения в начале этого решения :
XSLT 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="Undefined!!!" exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<w:document xmlns:w="Undefined!!!">
<w:body>
<xsl:copy-of select=
"/*/*/w:p[1]
|
/*/*/w:p[position() ge 2]
[xs:integer(substring-after(@pStyle,'Heading'))
lt
xs:integer(substring-after(preceding-sibling::*[1]/@pStyle,'Heading'))
]
"/>
</w:body>
</w:document>
</xsl:template>
</xsl:stylesheet>
XSLT 1.0:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="Undefined!!!">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<w:document xmlns:w="Undefined!!!">
<w:body>
<xsl:copy-of select=
"/*/*/w:p
[not(substring-after(@pStyle,'Heading')
>=
substring-after(preceding-sibling::*[1]/@pStyle,'Heading')
)
]
"/>
</w:body>
</w:document>
</xsl:template>
</xsl:stylesheet>
Все три вышеупомянутых преобразования XSLT дают требуемый, правильный результат .