【问题标题】:xsl:fo template match not firing on nested listxsl:fo 模板匹配未在嵌套列表上触发
【发布时间】:2014-02-11 12:37:04
【问题描述】:

我需要在应用 xsl:fo 的嵌套列表中为项目符号使用连字符。我有两个要匹配的模板,但只有一个正在应用。如果我只使用第一个模板,则外部列表会应用该模板。如果我只使用第二个模板,嵌套列表会应用该模板。我试图在第二个模板中匹配的模式是任何以列表项为父项的无序列表。非常感谢任何有关获得我想要的输出的帮助。

XML

<ThisNode>
<ul>
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three
        <ul>
            <li>Sub-Item One</li>
            <li>Sub-Item Two</li>
        </ul>
    </li>
    <li>Item Four</li>
    <li>Item Five</li>
</ul>
</ThisNode>

XSLT

<xsl:template match="ul">
<fo:list-block>
    <xsl:for-each select="./li">
        <fo:list-item>
            <fo:list-item-label end-indent="label-end()">
                <fo:block font-weight="bold">•</fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="8pt">
                <fo:block><xsl:value-of select="."/></fo:block>
            </fo:list-item-body>
        </fo:list-item>
    </xsl:for-each>
</fo:list-block>
</xsl:template>

<xsl:template match="li//ul">
<fo:list-block start-indent="8pt">
    <xsl:for-each select="./li">
        <fo:list-item>
            <fo:list-item-label end-indent="label-end()">
                <fo:block font-weight="bold">-</fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="16pt">
                <fo:block><xsl:value-of select="."/></fo:block>
            </fo:list-item-body>
        </fo:list-item>
    </xsl:for-each>
</fo:list-block>
</xsl:template>

<fo:block text-align="left">
    <xsl:apply-templates select="./ThisNode"/>
</fo:block>

期望的输出

• Item One
• Item Two
• Item Three
    - Sub-Item One
    - Sub-Item Two
• Item Four
• Item Five

仅使用第一个模板或同时使用两者的实际输出

• Item One
• Item Two
• Item ThreeSub-Item OneSub-Item Two
• Item Four
• Item Five

仅使用第二个模板的实际输出

Item One Item Two Item Three
    - Sub-Item One
    - Sub-Item Two
Item Four Item Five

【问题讨论】:

    标签: templates xslt xsl-fo


    【解决方案1】:

    这对于call-templatemode 来说似乎是区分这两种情况的好地方。外模板调用内模板:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    
       <xsl:template match="/">
          <fo:block text-align="left">
             <xsl:apply-templates select="ThisNode"/>
          </fo:block>
       </xsl:template>
    
    
       <xsl:template match="ul">
          <fo:list-block>
             <xsl:for-each select="li">
                <fo:list-item>
                   <fo:list-item-label end-indent="label-end()">
                      <fo:block font-weight="bold">•</fo:block>
                   </fo:list-item-label>
                   <fo:list-item-body start-indent="8pt">
                      <fo:block>
                         <!-- I'm not quite sure what you want here -->
                         <xsl:value-of select="text()"/>
                         <xsl:apply-templates select="ul" mode="inner"/>
                      </fo:block>
                   </fo:list-item-body>
                </fo:list-item>
             </xsl:for-each>
          </fo:list-block>
       </xsl:template>
    
       <xsl:template match="ul" mode="inner">
          <fo:list-block start-indent="8pt">
             <xsl:for-each select="./li">
                <fo:list-item>
                   <fo:list-item-label end-indent="label-end()">
                      <fo:block font-weight="bold">-</fo:block>
                   </fo:list-item-label>
                   <fo:list-item-body start-indent="16pt">
                      <fo:block>
                         <xsl:value-of select="."/>
                      </fo:block>
                   </fo:list-item-body>
                </fo:list-item>
             </xsl:for-each>
          </fo:list-block>
       </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

      【解决方案2】:

      以下样式表说明了一种可能的解决方案。您的方法并不遥远 - 但是,它无法解释 XSLT 处理器的行为。这个表达式:

      <xsl:value-of select="."/>
      

      默认情况下返回作为上下文节点子节点的任何文本节点。但在您的情况下(li 元素的模板匹配),输出 所有 后代文本节点,而不仅仅是 li 的直接子节点。

      因此,下面的样式表使用

      <xsl:value-of select="child::text()"/>
      

      取而代之的是检索li 元素的文本内容,而&lt;xsl:apply-templates&gt; 则处理属于它的子项的任何li 元素。

      正如你的标题所说,

      xsl:fo 模板匹配未在嵌套列表中触发

      您的诊断正确。这是因为 - 一旦在 li 的模板匹配中 - 您不会让 XSLT 处理器处理后代 li 元素。

      样式表

      <?xml version="1.0" encoding="utf-8"?>
      
      <xsl:stylesheet version="2.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="/ThisNode">
            <fo:root>
               <fo:layout-master-set>
                  <fo:simple-page-master master-name="simple"
                                    page-height="29.7cm"
                                    page-width="21cm"
                                    margin-top="1cm"
                                    margin-bottom="2cm"
                                    margin-left="2.5cm"
                                    margin-right="2.5cm">
                     <fo:region-body margin-top="3cm"/>
                     <fo:region-before extent="3cm"/>
                     <fo:region-after extent="1.5cm"/>
                  </fo:simple-page-master>
               </fo:layout-master-set>
      
               <fo:page-sequence master-reference="simple">
                  <fo:flow flow-name="xsl-region-body">
                     <xsl:apply-templates/>
                  </fo:flow>
               </fo:page-sequence>
            </fo:root>
         </xsl:template>
      
         <xsl:template match="ul[parent::ThisNode]">
            <fo:list-block>
               <xsl:apply-templates/>
            </fo:list-block>
         </xsl:template>
      
         <xsl:template match="ul[parent::li]">
               <xsl:apply-templates/>
         </xsl:template>
      
         <xsl:template match="li">
            <fo:list-item>
               <xsl:choose>
                  <xsl:when test="parent::ul/parent::ThisNode">
                      <fo:list-item-label start-indent="1cm">
                         <fo:block font-weight="bold">&#x2022;</fo:block>
                      </fo:list-item-label>
                      <fo:list-item-body start-indent="1.5cm">
                         <fo:block><xsl:value-of select="child::text()"/></fo:block>
                      </fo:list-item-body>
                  </xsl:when>
                  <xsl:otherwise>
                      <fo:list-item-label start-indent="3cm">
                         <fo:block font-weight="bold">-</fo:block>
                      </fo:list-item-label>
                      <fo:list-item-body start-indent="3.5cm">
                         <fo:block><xsl:value-of select="."/></fo:block>
                      </fo:list-item-body>
                  </xsl:otherwise>
               </xsl:choose>  
            </fo:list-item>
            <xsl:apply-templates/>
         </xsl:template>
      
      </xsl:stylesheet>
      

      输出 (XSL-FO)

      <?xml version="1.0" encoding="UTF-8"?>
      <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
         <fo:layout-master-set>
            <fo:simple-page-master master-name="simple" page-height="29.7cm" page-width="21cm" margin-top="1cm"
                                   margin-bottom="2cm"
                                   margin-left="2.5cm"
                                   margin-right="2.5cm">
               <fo:region-body margin-top="3cm"/>
               <fo:region-before extent="3cm"/>
               <fo:region-after extent="1.5cm"/>
            </fo:simple-page-master>
         </fo:layout-master-set>
         <fo:page-sequence master-reference="simple">
            <fo:flow flow-name="xsl-region-body">
               <fo:list-block>
                  <fo:list-item>
                     <fo:list-item-label start-indent="1cm">
                        <fo:block font-weight="bold">•</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="1.5cm">
                        <fo:block>Item One</fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Item One
          <fo:list-item>
                     <fo:list-item-label start-indent="1cm">
                        <fo:block font-weight="bold">•</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="1.5cm">
                        <fo:block>Item Two</fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Item Two
          <fo:list-item>
                     <fo:list-item-label start-indent="1cm">
                        <fo:block font-weight="bold">•</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="1.5cm">
                        <fo:block>Item Three
      
          </fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Item Three
      
                  <fo:list-item>
                     <fo:list-item-label start-indent="3cm">
                        <fo:block font-weight="bold">-</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="3.5cm">
                        <fo:block>Sub-Item One</fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Sub-Item One
                  <fo:list-item>
                     <fo:list-item-label start-indent="3cm">
                        <fo:block font-weight="bold">-</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="3.5cm">
                        <fo:block>Sub-Item Two</fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Sub-Item Two
      
      
          <fo:list-item>
                     <fo:list-item-label start-indent="1cm">
                        <fo:block font-weight="bold">•</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="1.5cm">
                        <fo:block>Item Four</fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Item Four
          <fo:list-item>
                     <fo:list-item-label start-indent="1cm">
                        <fo:block font-weight="bold">•</fo:block>
                     </fo:list-item-label>
                     <fo:list-item-body start-indent="1.5cm">
                        <fo:block>Item Five</fo:block>
                     </fo:list-item-body>
                  </fo:list-item>Item Five
      </fo:list-block>
            </fo:flow>
         </fo:page-sequence>
      </fo:root>
      

      输出 (PDF)

      【讨论】:

        猜你喜欢
        • 2013-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-16
        • 2012-06-12
        • 2019-08-15
        • 1970-01-01
        相关资源
        最近更新 更多