我想通过使用xslt 2.0将一种xml格式转换为另一种xml格式。现在我想获取上下文节点的下一个紧随着的:: node()元素。例如,
这是我的xml文档:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:v="urn:schemas-microsoft-com:vml">
<w:body>
<w:p>para1</w:p> <!-- assume this as context node -->
<w:tbl>table data 1</w:tbl>
<w:tbl>table data 2</w:tbl>
<w:p>para2</w:p>
<w:tbl>table data 3</w:tbl>
<w:tbl>table data 4</w:tbl>
<w:tbl>table data 5</w:tbl>
<w:tbl>table data 6</w:tbl>
<w:p>para3</w:p>
</w:body>
</w:document>
因此,根据上面xml文件中提到的上下文节点,我想只选择表数据1和表数据。
例如,如果我的上下文节点是para2,那么我只想选择表数据3,表数据4,表数据5和表数据6。
所以,我写过像这样的xslt,
<xsl:for-each select="following::node()/self::w:tbl">
<xsl:choose>
<xsl:when test="self::w:tbl">
<xsl:apply-templates select="self::w:tbl"></xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:for-each>
但它产生了错误的结果......
请指导我摆脱这个问题...
答案 0 :(得分:1)
假设您被定位在 w:p 元素上,您可以获得以下 w:tbl 的所有兄弟姐妹,其中第一个前面的 w:p 是当前元素
<xsl:apply-templates
select="following-sibling::w:tbl
[generate-id(preceding-sibling::w:p[1]) = generate-id(current())]" />
使用 xsl:key 可以稍微整理一下。如果您要定义以下密钥:
<xsl:key name="tbl" match="w:tbl" use="generate-id(preceding-sibling::w:p[1])" />
然后您可以获得以下 w:tbl 元素:
<xsl:apply-templates select="key('tbl', generate-id())" />
例如,给定以下XSLT
<xsl:stylesheet version="1.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="w v">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="tbl" match="w:tbl" use="generate-id(preceding-sibling::w:p[1])" />
<xsl:template match="w:body">
<xsl:apply-templates select="w:p[1]" />
</xsl:template>
<xsl:template match="w:p">
<xsl:apply-templates select="key('tbl', generate-id())" />
</xsl:template>
<xsl:template match="w:tbl">
<table><xsl:value-of select="." /></table>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容:
<table>table data 1</table>
<table>table data 2</table>
请注意,这是一个XSLT1.0解决方案。可能还有其他方法可以在XSLT2.0中使用。
答案 1 :(得分:1)
这是一个可能有用的功能:
<xsl:function name="f:adjacently-following" as="element()*">
<xsl:param name="start" as="element()"/>
<xsl:param name="elementName" as="xs:QName"/>
<xsl:variable name="next" select="$start/following-sibling::*[1]"/>
<xsl:if test="node-name($next) = $elementName">
<xsl:sequence select="$next, f:adjacently-following($next, $elementName)"/>
</xsl:if>
</xsl:function>
然后你可以拨打f:adjacently-following(., xs:QName('w:tbl'))
答案 2 :(得分:1)
这个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"
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="/">
<root>
<xsl:for-each-group select="w:document/w:body/(w:p|w:tbl)" group-starting-with="w:p" >
<p>
<xsl:apply-templates select="current-group()" />
</p>
</xsl:for-each-group>
</root>
</xsl:template>
<xsl:template match="w:tbl">
<table>
<xsl:value-of select="." />
</table>
</xsl:template>
</xsl:stylesheet>
...当应用于此输入文档时......
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:v="urn:schemas-microsoft-com:vml">
<w:body>
<w:p>para1</w:p>
<!-- assume this as context node -->
<w:tbl>table data 1</w:tbl>
<w:tbl>table data 2</w:tbl>
<w:p>para2</w:p>
<w:tbl>table data 3</w:tbl>
<w:tbl>table data 4</w:tbl>
<w:tbl>table data 5</w:tbl>
<w:tbl>table data 6</w:tbl>
<w:p>para3</w:p>
</w:body>
</w:document>
... ...产量
<root>
<p>para1<table>table data 1</table>
<table>table data 2</table>
</p>
<p>para2<table>table data 3</table>
<table>table data 4</table>
<table>table data 5</table>
<table>table data 6</table>
</p>
<p>para3</p>
</root>