在 XSL FO 中创建多级列表

creating Multi-level lists in XSL FO

提问人:Daniel 提问时间:9/19/2023 最后编辑:Siebe JongebloedDaniel 更新时间:9/19/2023 访问量:45

问:

我正在尝试创建多级列表输出。im 在 XML 1.0 中使用通过 apache FOP 运行的 XSLT

我使用如下所示的 XML 输入,其中 procedureList 中有许多不同的过程,这些过程有许多步骤。子步骤嵌入在步骤中。

<ProcedureList>
<Procedure title="The First Procedure" type="Removal">
<Steps> 
   <Step id="1">Step 1 </Step>
   <Step id="2">Step 2 </Step>
   <Step id="3">Step 3 <Step id="4">Step 4 <Step id="5">Step 5 </Step></Step></Step>
</Steps>
</Procedure>
<Procedure title="The Second Procedure" type="removal">
<Steps> 
   <Step id="6">Step 6 </Step>
   <Step id="7">Step 7 <Step id="8">Step 8</Step></Step>
</Steps>
</Procedure>
</ProcedureList>

之后的输出 IM 是

1. The First Procedure
1.1 Step 1 
1.2 Step 2 
1.3 Step 3 
1.3.a Step 4 
1.3.a.i Step 5

2. The Second Procedure
2.1 Step 6 
2.2 Step 7 
2.2.a Step 8

使用下面的内容,我接近正确的答案(位置作为前导数字传递给模板,具体取决于该过程在文档中发生的位置。

  <xsl:template match="Step">
    <xsl:param name="position" />
    <fo:block >
      <xsl:apply-templates select="WCN" />
      <xsl:if test="normalize-space(text()) != ''">
        
        <fo:block text-indent='-15mm' start-indent='15mm' xsl:use-attribute-sets="BodyText" wrap-option="wrap" white-space="pre">
          <xsl:if test="$position != ''">
            <xsl:value-of select="$position"/><xsl:text>.</xsl:text>
          </xsl:if>
          <xsl:if test="$position = ''">
            <xsl:text>         </xsl:text>
          </xsl:if>
          <xsl:number format="1.1.a.i.a.i" count="Step" level="multiple"/><xsl:text>      </xsl:text><xsl:apply-templates select="text()"/></fo:block>
      </xsl:if>
      
      <xsl:apply-templates select="Step" />
      
    </fo:block>
  </xsl:template>

我遇到的问题是当我在文档的一个区域需要两个相同类型的过程时。 我称模板为

<xsl:choose>
  <xsl:when test="root/ProcedureList/Procedure[@type='inspection' or @type='repair'] != ''">
    <xsl:for-each select="root/ProcedureList/Procedure[@type='inspection' or @type='repair']">
      <xsl:apply-templates >
        <xsl:with-param name="position" select="8" />
      </xsl:apply-templates>
    </xsl:for-each>
  </xsl:when>
  <xsl:otherwise>
    <fo:block xsl:use-attribute-sets="BodyText">Not Applicable</fo:block>
  </xsl:otherwise>
</xsl:choose>

我得到这样的输出

1. The First Procedure
1.1 Step 1 
1.2 Step 2 
1.3 Step 3 
1.3.a Step 4 
1.3.a.i Step 5

1. The Second Procedure
1.1 Step 6 
1.2 Step 7 
1.2.a Step 8
xml 列表 xslt xslt-1.0 xsl-fo

评论


答:

0赞 Siebe Jongebloed 9/19/2023 #1

只是改变

<xsl:number format="1.1.a.i.a.i" count="Step" level="multiple"/>

<xsl:number format="1.1.a.i.a.i" count="Procedure|Step" level="multiple"/>

评论

0赞 Daniel 9/19/2023
感谢您的回复,但不幸的是,这会从 XML 中提取过程“order”。因此,如果 XML 有 3 个过程,则第 3 个过程将出现 3.1、3.2、3.3 等,但这可能是该类型的第一个过程。如果这有意义
1赞 Siebe Jongebloed 9/19/2023
你能改变你的例子和预期的结果吗?
0赞 John Ernst 9/19/2023 #2

很难直接对你的代码进行评论,因为我没有看到所有的内容,而且你提供的代码不适用于你的示例XML。但是,解决基本问题相当容易。您将需要添加过滤器和格式。并将其应用到您的程序中。如果需要,您可以向模板添加模式并应用模板。

<xsl:template match="ProcedureList">
  <xsl:value-of select="'&#13;'"/>
  <xsl:apply-templates select="Procedure"/>
</xsl:template>

<xsl:template match="Procedure">
  <xsl:value-of select="concat(position(), '. ', @title)"/>
  <xsl:value-of select="'&#13;'"/>
  <xsl:apply-templates select="Steps/Step">
    <xsl:with-param name="procedure" select="concat(position(), '.')"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="Step">
  <xsl:param name="procedure" />
  <xsl:value-of select="$procedure"/>
  <xsl:number format="1.a.i.a.i" count="Step" level="multiple"/>
  <xsl:value-of select="concat(' ', normalize-space(text()))"/>
  <xsl:value-of select="'&#13;'"/>

  <xsl:apply-templates select="Step">
    <xsl:with-param name="procedure" select="$procedure"/>
  </xsl:apply-templates>
</xsl:template>  

评论

0赞 Siebe Jongebloed 9/21/2023
@Daniel说:“不幸的是,这从XML中提取了过程”order”。不是在这种情况下?
0赞 John Ernst 9/22/2023
@SiebeJongebloed 这绝对是按 XML 顺序拉动的。但是,可以通过对 apply-templates 进行排序或多次调用 apply-templates 来更改过程的顺序,每个过程类型一次。
0赞 John Ernst 9/22/2023
<xsl:template match=“ProcedureList”> <xsl:value-of select=“'&#13;'”/> <xsl:apply-templates select=“Procedure[@type='Removal']”/> <xsl:apply-templates select=“Procedure[@type='ADifferentType']”/> </xsl:template>