格式化表列以忽略重复项XSLT-1.0
我希望有人能用XSLT1.0中的概念为我指明正确的方向。我正在生成一个PDF,因此代码有点长,我认为只包含相关的位更合适 我有类似于以下框架的XML(完整的XML有几十行,每行包含的不仅仅是生产者和发布者): 以这种方式等等 在我的XSLT中产生这种情况的代码的主要部分是:格式化表列以忽略重复项XSLT-1.0,xslt,xslt-1.0,xsl-fo,Xslt,Xslt 1.0,Xsl Fo,我希望有人能用XSLT1.0中的概念为我指明正确的方向。我正在生成一个PDF,因此代码有点长,我认为只包含相关的位更合适 我有类似于以下框架的XML(完整的XML有几十行,每行包含的不仅仅是生产者和发布者): 以这种方式等等 在我的XSLT中产生这种情况的代码的主要部分是: <xsl:template match ="table"> <fo:table> <fo:table-body font-size="10pt"
<xsl:template match ="table">
<fo:table>
<fo:table-body font-size="10pt"
font-family="sans-serif"
line-height="10pt"
space-after.optimum="3pt">
<xsl:for-each select="row">
<fo:table-row>
<fo:table-cell width="2.125in"
height="0.2in">
<xsl:choose>
<xsl:apply-templates select="PRODUCER"/>
</xsl:choose>
</fo:table-cell>
<fo:table-cell width="3.25in"
height="0.2in">
<xsl:apply-templates select="PUBLICATION_CODE_-_NAME"/>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="PRODUCER">
<fo:block>
<xsl:value-of select="@value"/>
</fo:block>
</xsl:template>
<xsl:template match="PUBLICATION_CODE_-_NAME">
<fo:block>
<xsl:value-of select="@value"/>
</fo:block>
</xsl:template>
我尝试这样做的方式是在XSLT的这一部分中
<xsl:template match="PRODUCER">
<fo:block>
<xsl:value-of select="@value"/>
</fo:block>
</xsl:template>
在这一点上,据我所知,上下文节点是生产者。因此,为了比较前几行中的生产者值,我需要使用../previous sibling的效果,以便找到最后一行的previous sibling(而不是PRODUCER)。此外,信息已经由制作人订购,因此我只需要查看前面最接近的兄弟姐妹,而不是所有兄弟姐妹
我试图使用以下代码来解决此问题:
<xsl:template match="PRODUCER">
<fo:block>
<xsl:if test="not(../preceding-sibling::PRODUCER/@value = self/@value>
<xsl:value-of select="@value"/>
</xsl:if>
</fo:block>
</xsl:template>
它可以通过分组来完成,也可以通过前面的兄弟姐妹来完成。我注意到你说的是“几十”。。。我不会担心使用分组。我用2000行运行了这个示例,执行时间为2.3秒(使用Saxon在氧气中进行调试),0.1秒不进行调试。几十个需要几分之一秒的时间。我在这里扩展了您的示例,包括第一次出现的测试,该测试之前没有兄弟姐妹。你也可以结合一些东西,但我留下了这个,这样你可以看到不同的决定:
示例XML:
<root>
<table>
<row>
<PRODUCER>1</PRODUCER>
<PUBLICATION>A</PUBLICATION>
</row>
<row>
<PRODUCER>1</PRODUCER>
<PUBLICATION>B</PUBLICATION>
</row>
<row>
<PRODUCER>1</PRODUCER>
<PUBLICATION>C</PUBLICATION>
</row>
<row>
<PRODUCER>2</PRODUCER>
<PUBLICATION>B</PUBLICATION>
</row>
<row>
<PRODUCER>2</PRODUCER>
<PUBLICATION>C</PUBLICATION>
</row>
<row>
<PRODUCER>3</PRODUCER>
<PUBLICATION>A</PUBLICATION>
</row>
<row>
<PRODUCER>4</PRODUCER>
<PUBLICATION>B</PUBLICATION>
</row>
</table>
</root>
1.
A.
1.
B
1.
C
2.
B
2.
C
3.
A.
4.
B
XSL,用于测试前一个同级,将其放入一个变量中进行处理,并仅选择前一个变量[1]:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match ="table">
<fo:table>
<fo:table-body font-size="10pt"
font-family="sans-serif"
line-height="10pt"
space-after.optimum="3pt">
<xsl:for-each select="row">
<fo:table-row>
<fo:table-cell width="2.125in"
height="0.2in">
<xsl:apply-templates select="PRODUCER"/>
</fo:table-cell>
<fo:table-cell width="3.25in"
height="0.2in">
<xsl:apply-templates select="PUBLICATION"/>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="PRODUCER">
<fo:block>
<!-- Get the previous row element to the one I am in -->
<xsl:variable name="test" select="parent::row/preceding-sibling::row[1]"/>
<xsl:choose>
<!-- First test, do we have a row? -->
<xsl:when test="$test">
<!-- Yes we have a previous row -->
<xsl:choose>
<!-- Next, is the previous row's PRODUCER text the same as ours? -->
<xsl:when test="$test/PRODUCER/text() = text()">
<!-- It is, output nothing -->
<fo:leader/>
</xsl:when>
<xsl:otherwise>
<!-- It is not, so output it -->
<xsl:value-of select="concat('Producer ',.)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<!-- We are the first row (no previous one) so output it -->
<xsl:otherwise>
<xsl:value-of select="concat('Producer ',.)"/>
</xsl:otherwise>
</xsl:choose>
</fo:block>
</xsl:template>
<xsl:template match="PUBLICATION">
<fo:block>
<xsl:value-of select="concat('Publication ',.)"/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
输出:
<fo:table xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:table-body font-size="10pt" font-family="sans-serif" line-height="10pt" space-after.optimum="3pt">
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 1</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication A</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>
<fo:leader/>
</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication B</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>
<fo:leader/>
</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication C</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 2</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication B</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>
<fo:leader/>
</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication C</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 3</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication A</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 4</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication B</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
制作人1
出版物A
出版物B
出版物C
制作人2
出版物B
出版物C
制片人3
出版物A
制片人4
出版物B
这是一个分组问题。请参阅:这里还有很多这样的例子。XSLT1.0中的分组技巧是必要的。这门语言很有能力做到这一点,但它不是直截了当的,在语言中也找不到分组。经过几次努力,你将成为一名专家!谢谢你的意见。我一直在回顾明钦方法。我本周刚开始使用这项技术,发现学习曲线有点陡峭。我希望在完全理解我正在生成的这份报告之后,能够避免再问更多的问题。“我用2000行运行了这个示例,执行时间为2.3秒(在使用Saxon的氧气调试模式下)。”不同的处理器,不同的统计数据。遵循良好的实践是值得的。是的,对于2250行saxon6,没有调试,时间是0.1秒。Xalan为5秒,NET2.0为1.3秒。当然,2250比几十大。非常感谢凯文,这正是我想要的。
<root>
<table>
<row>
<PRODUCER>1</PRODUCER>
<PUBLICATION>A</PUBLICATION>
</row>
<row>
<PRODUCER>1</PRODUCER>
<PUBLICATION>B</PUBLICATION>
</row>
<row>
<PRODUCER>1</PRODUCER>
<PUBLICATION>C</PUBLICATION>
</row>
<row>
<PRODUCER>2</PRODUCER>
<PUBLICATION>B</PUBLICATION>
</row>
<row>
<PRODUCER>2</PRODUCER>
<PUBLICATION>C</PUBLICATION>
</row>
<row>
<PRODUCER>3</PRODUCER>
<PUBLICATION>A</PUBLICATION>
</row>
<row>
<PRODUCER>4</PRODUCER>
<PUBLICATION>B</PUBLICATION>
</row>
</table>
</root>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match ="table">
<fo:table>
<fo:table-body font-size="10pt"
font-family="sans-serif"
line-height="10pt"
space-after.optimum="3pt">
<xsl:for-each select="row">
<fo:table-row>
<fo:table-cell width="2.125in"
height="0.2in">
<xsl:apply-templates select="PRODUCER"/>
</fo:table-cell>
<fo:table-cell width="3.25in"
height="0.2in">
<xsl:apply-templates select="PUBLICATION"/>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="PRODUCER">
<fo:block>
<!-- Get the previous row element to the one I am in -->
<xsl:variable name="test" select="parent::row/preceding-sibling::row[1]"/>
<xsl:choose>
<!-- First test, do we have a row? -->
<xsl:when test="$test">
<!-- Yes we have a previous row -->
<xsl:choose>
<!-- Next, is the previous row's PRODUCER text the same as ours? -->
<xsl:when test="$test/PRODUCER/text() = text()">
<!-- It is, output nothing -->
<fo:leader/>
</xsl:when>
<xsl:otherwise>
<!-- It is not, so output it -->
<xsl:value-of select="concat('Producer ',.)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<!-- We are the first row (no previous one) so output it -->
<xsl:otherwise>
<xsl:value-of select="concat('Producer ',.)"/>
</xsl:otherwise>
</xsl:choose>
</fo:block>
</xsl:template>
<xsl:template match="PUBLICATION">
<fo:block>
<xsl:value-of select="concat('Publication ',.)"/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
<fo:table xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:table-body font-size="10pt" font-family="sans-serif" line-height="10pt" space-after.optimum="3pt">
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 1</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication A</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>
<fo:leader/>
</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication B</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>
<fo:leader/>
</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication C</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 2</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication B</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>
<fo:leader/>
</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication C</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 3</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication A</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell width="2.125in" height="0.2in">
<fo:block>Producer 4</fo:block>
</fo:table-cell>
<fo:table-cell width="3.25in" height="0.2in">
<fo:block>Publication B</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>