下面是我的xml文件。
<xml>
<top>
<main>
<firstname>John</firstname>
<lastname>John</lastname>
<table></table>
<chapter>
<firstname>Alex</firstname>
<lastname>Robert</lastname>
<p>Sample text chap</p>
<figure name="f1.svg"></figure>
<chapter>
<firstname>Rebec</firstname>
<lastname></lastname>
<p>Sample text</p>
<figure name="f2.svg"></figure>
</chapter>
</chapter>
</main>
</top>
</xml>
期望的输出:
<bold>John
table
<bold>Robert
Sample text chap
f1.svg
<bold> Rebec
Sample text
f2.svg
解释:我写了一个xslt来做到这一点。我需要动态获取xml节点。我不能写:xsl:apply-templates select ='main / lastname'。因为我的xml格式可以随时更改。 我尝试过使用'$ root / *'首先获取所有xml节点的逻辑。然后,如果遇到'table'元素,我使用xsl:apply-templates select ='current()[name()='TABLE']'并执行表创建操作。 这很好用。我得到了所需的输出,但我的图形元素只在输出的每个位置显示f1.svg。 f2.svg未显示。 我如何只匹配'lastname'并使其变为粗体? 我想使代码尽可能通用/模块化,以便它遍历xml树的所有元素,并在特定节点上进行一些格式化。 下面是递归的xslt。有了这个,我的数据就会重复出现。我正在编写递归模板,因为xslt不是顺序的。
XSLT:
<xsl:call-template name="FetchNodes">
<xsl:with-param name="endIndex" select="$NumberOfNodes" />
<xsl:with-param name="startIndex" select="1" />
<xsl:with-param name="context" select="$root/*" />
</xsl:call-template>
<xsl:template name="FetchNodes">
<xsl:param name="endIndex" />
<xsl:param name="startIndex" />
<xsl:param name="context" />
<xsl:if test="$startIndex <= $endIndex">
<xsl:if test="$context[$startIndex][name() = 'table']"">
<xsl:apply-templates select="$context[$startIndex][name() = 'table']"" mode="table" />
</xsl:if>
<xsl:call-template name="FetchNodes">
<xsl:with-param name="endIndex" select="$endIndex" />
<xsl:with-param name="startIndex" select="$startIndex + 1"/>
<xsl:with-param name="context" select="$context" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="node()" mode="table">
<xsl:value-of select="node()" />
</xsl:template>
使用上面的xslt,应用模板的xpath中有些不正确。输出不正确。
我想要XSL FO输出。
有人能提出什么建议吗?
答案 0 :(得分:1)
显示“f1.svg”而不是“f2.svg”的问题是因为这行
<xsl:variable name="ImageName">
<xsl:value-of select="$root/*/chapter/figure/@name" />
</xsl:variable>
此时您已经定位在数字上,因此您只需要在此处使用相对xpath表达式。您当前使用的是绝对路径,因此无论您的上下文如何,它都将始终返回第一个 @name 属性。它应该看起来这个
<xsl:variable name="ImageName">
<xsl:value-of select="@name" />
</xsl:variable>
或者更好,就像这样
<xsl:variable name="ImageName" select="@name" />
说完了,代码就在一个模板中,试图匹配一个 FIG 元素,这个元素在你向我们展示的XML中不存在。您实际上可以简化模板匹配,例如
<xsl:template match="figure" mode="figure">
至于粗体,您只需将 font-weight 属性添加到要制作粗体的任何块中。像这样:
<xsl:choose>
<xsl:when test="self::lastname">
<fo:inline font-weight="bold"><xsl:value-of select="text()" /></fo:inline>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="text()" />
</xsl:otherwise>
</xsl:choose>
编辑:说了这么多,你可能没有采取正确的方法解决问题。使用模板匹配可能会更好,利用XSLT的内置模板来浏览文档。基本上,只需为要匹配的每个元素编写一个模板,然后生成输出,然后继续匹配其子元素。
例如,要将章节变为 fo:block ,请执行此操作
<xsl:template match="chapter">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
要以粗体输出名字,请执行此操作
<xsl:template match="firstname">
<fo:inline font-weight="bold">
<xsl:value-of select="text()"/>
</fo:inline>
</xsl:template>
要将数字转换为图像,请执行此操作(请注意,此处使用属性值模板,花括号表示要计算的表达式,而不是按字面输出)
<xsl:template match="figure">
<fo:block>
<fo:external-graphic src="../resources/{@name}" content-height="60%" scaling="uniform" padding-left="2cm"/>
</fo:block>
</xsl:template>
尝试将此XSLT作为起点,并在其上构建
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="main">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="chapter">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="firstname">
<fo:inline font-weight="bold">
<xsl:value-of select="text()"/>
</fo:inline>
</xsl:template>
<xsl:template match="lastname"/>
<xsl:template match="figure">
<fo:block>
<fo:external-graphic src="../resources/{@name}" content-height="60%" scaling="uniform" padding-left="2cm"/>
</fo:block>
</xsl:template>
</xsl:stylesheet>