我正在尝试使用XSLT从docx的document.xml文件中检索TOC
这是我的XSLT:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" exclude-result-prefixes="w" version="2.0">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="w:sdt">
<xsl:element name="root">
<xsl:attribute name="label">
<xsl:value-of select="w:sdtPr/w:docPartObj/w:docPartGallery/@w:val"/>
</xsl:attribute>
<xsl:for-each select="w:sdtContent/w:p">
<xsl:if test="w:pPr/w:pStyle/@w:val">
<xsl:element name="sec">
<xsl:attribute name="label">
<xsl:value-of select="w:pPr/w:pStyle/@w:val"/>
</xsl:attribute>
<xsl:attribute name="anchor">
<xsl:value-of select="w:hyperlink/@w:anchor"/>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="w:hyperlink/w:r/w:t"/>
</xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:transform>
我得到了理想的结果,但在w:sdtContent范围之外还有额外的w:p标记值。
我是XSLT的初学者,不知道我在这里做错了什么。
(如果源xml会有帮助,请告诉我,我会在这里发布。)
答案 0 :(得分:2)
XSLT使用a set of default rules从根节点开始处理其输入。可以覆盖这些默认规则 - 但您不能这样做。我怀疑你看到的不必要的额外输出来自默认规则。
您的样式表包含一个模板<xsl:template match="w:sdt">
,而XSLT处理器 运行该模板,但只有当它遍历输入文档时才会到达<w:sdt>
。
如果您想自己从根节点开始并且指示 XSLT处理器应该查看哪些节点,请通过编写与根节点匹配的模板来覆盖默认行为(<xsl:template match="/">
)。
<xsl:transform
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
exclude-result-prefixes="w"
>
<xsl:output indent="yes" method="xml" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:apply-temmplates select="//w:sdt" />
</xsl:template>
<xsl:template match="w:sdt">
<root label="{w:sdtPr/w:docPartObj/w:docPartGallery/@w:val}" />
<xsl:apply-templates select="w:sdtContent/w:p[w:pPr/w:pStyle/@w:val]" />
</root>
</xsl:template>
<xsl:template match="w:sdtContent/w:p">
<sec
label="{w:pPr/w:pStyle/@w:val}"
anchor="{w:hyperlink/@w:anchor}"
title="{w:hyperlink/w:r/w:t}"
/>
</xsl:template>
</xsl:transform>
其他说明:
<xsl:element name="foo">
。写<foo>
。<xsl:attribute name="bar">
写<foo bar="{xpath-expr}">
。<xsl:for-each>
。使用<xsl:apply-templates>
和<xsl:template>
。<xsl:if>
来过滤您要处理的节点。编写一个适当的XPath表达式,仅选择要处理的节点。<xsl:apply-templates>
works。