0

使用 Apache FOP,我想在 PDF 文件中收集一些信息。XML源有一些子节点a到e,比方说

<node>
   <a>some val</a>
   <b>some other val</b>
   <c>more val</c>
   <d>even more val</d>
   <e>a last val</e>
</node>

我不想显示所有这些。a,b,c 应始终显示,但可能为空。显示值的最大数量为 3。因此,d 和 e 是可选的,必须按此顺序保留。

遗憾的是,无法修改 XML 结构。

什么是合适的 XSLT?我试过了

<xsl:for-each select="child::*[name()='a' or name() = 'b' or name() = 'c' or name() = 'd' or name() = 'e'][string-length(.)&gt;0]">
    <xsl:if test="position() &lt;= 3">
        <xsl:value-of select="name()"/>
    </xsl:if>
</xsl:for-each>

但这并没有给我带来有序列表。:(

4

3 回答 3

1

<xsl:sort />应该很高兴。

在您的情况下,它将是:

<xsl:sort select="name()"/>

因此尝试:

    <xsl:for-each select="child::*[name()='a' or name() = 'b' or name() = 'c' or name() = 'd' or name() = 'e'][string-length(.)&gt;0]">
        <xsl:sort select="name()"/>
        <xsl:if test="position() &lt;= 3">
            <xsl:value-of select="name()"/>
        </xsl:if>
    </xsl:for-each>

更新:因为在实时输入 XML 中没有有用的信息可供排序,所以您可以添加一些元信息。存储元信息的位置取决于 xslt 处理器的功能。

如果你可以使用 node-set() 扩展,你可以尝试这样的事情:

将变量添加到具有预期顺序的样式表。

xsl:variable name="myOrder">
        <order name="a" pos="1" />
        <order name="b" pos="3" />
        <order name="c" pos="2" />
        <order name="d" pos="4" />
        <order name="e" pos="5" />
    </xsl:variable>

通过以下方式使此变量可用作节点集:

<xsl:variable name="Order" select="exsl:node-set($myOrder)" />

借助此变量进行排序。

<xsl:sort select="$Order/order[@name= name(current())]/@pos"/>
于 2013-07-15T15:09:52.453 回答
1

@Florian Ruh,您声明的要求不是自洽的:“我不想显示所有这些。a,b,c 应始终显示。显示值的最大数量为 3。所以,d 和 e 是可选的,并且必须按该顺序保存。”

如果一直显示a、b和c,并且显示值的最大数量是3,那么d和3就没有机会显示了。

请说明您的要求。

请注意,使用 name() 函数的形式非常糟糕。

相当于:

<xsl:for-each select="child::*[name()='a' or name() = 'b' or name() = 'c' or name() = 'd' or name() = 'e'][string-length(.)&gt;0]">

是:

<xsl:for-each select="(a|b|c|d|e)[string(.)]">

...我提出的方法是命名空间安全的,而您使用的方法不是。

于 2013-07-15T16:03:12.333 回答
0

也许我理解不正确,但是如果您只想将前三个项目返回到有序列表中,您可以执行类似的操作

<xsl:template match="node">
<fo:list-block>
<xsl:apply-templates/>
</fo:list-block>
</xsl:template>

<xsl:template match="node/*[4] | node/*[5]"/>
<xsl:template match="node/*[1] | node/*[2] | node/*[3]">
<fo:list-item>
<fo:list-item-label>
<fo:block><xsl:value-of select="position()"/></fo:block>
</fo:list-item-label>
<fo:list-item-body>
<fo:block><xsl:value-of select="."/></fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>

这将忽略任何第 4 和第 5 个元素,但按文档顺序处理第一个、第二个和第三个元素(因为这是遇到它们的顺序)。

于 2013-07-15T16:17:53.067 回答