【问题标题】:Microsoft WordDOCX Nested list solution is not working as expectedMicrosoft WordDOCX 嵌套列表解决方案未按预期工作
【发布时间】:2017-04-04 12:23:08
【问题描述】:

您好,我尝试修复 XSLT 2.0 中的嵌套列表元素,转换为 HTML 和我的 XML 就像上面一样;

<w:p w:rsidR="008845A9" w:rsidRPr="001509B0" w:rsidRDefault="008845A9" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
    </w:pPr>
</w:p>
<w:p w:rsidR="001207E2" w:rsidRPr="001509B0" w:rsidRDefault="001207E2" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>First Item</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="00AD36E6" w:rsidRPr="001509B0" w:rsidRDefault="00AD36E6" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Second Item</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="00AD36E6" w:rsidRPr="001509B0" w:rsidRDefault="00AD36E6" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Third Item</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="002B7A91" w:rsidRPr="001509B0" w:rsidRDefault="002B7A91" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="2"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Third Item – One</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="002B7A91" w:rsidRPr="001509B0" w:rsidRDefault="002B7A91" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="2"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t xml:space="preserve">Third Item </w:t>
    </w:r>
    <w:r w:rsidR="006551A3" w:rsidRPr="001509B0">
        <w:t>–</w:t>
    </w:r>
    <w:r w:rsidRPr="001509B0">
        <w:t xml:space="preserve"> Two</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="006551A3" w:rsidRPr="001509B0" w:rsidRDefault="006551A3" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="3"/>
            <w:numId w:val="6"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t xml:space="preserve">Sample Item </w:t>
    </w:r>
    <w:r w:rsidR="00554D9D" w:rsidRPr="001509B0">
        <w:t>A</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="006551A3" w:rsidRPr="001509B0" w:rsidRDefault="00554D9D" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="3"/>
            <w:numId w:val="6"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Sample Item B</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="002B7A91" w:rsidRPr="001509B0" w:rsidRDefault="002B7A91" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Fo</w:t>
    </w:r>
    <w:r w:rsidR="00565721" w:rsidRPr="001509B0">
        <w:t>u</w:t>
    </w:r>
    <w:r w:rsidRPr="001509B0">
        <w:t>rth Item</w:t>
    </w:r>
</w:p>

还有完整的 XSLT

<xsl:output method="html" doctype-system="about:legacy-compat"/>
<xsl:template match="/">
    <html>
        <head>
            <title/>
        </head>
        <body>
            <xsl:apply-templates/>
            <ol>
                <xsl:call-template name="grouping">
                    <xsl:with-param name="par" select="w:document/w:body/w:p[1]"/>
                </xsl:call-template>
            </ol>
        </body>
    </html>
</xsl:template>
<xsl:template name="grouping">
    <xsl:param name="par"/>
    <xsl:choose>
        <xsl:when test="$par/w:pPr/w:numPr/w:ilvl/@w:val >0">
            <xsl:variable name="level" select="$par/w:pPr/w:numPr/w:ilvl/@w:val"/>
            <li>
                <xsl:value-of select="$par/w:r/w:t"/>
            </li>
            <xsl:call-template name="order">
                <xsl:with-param name="par" select="$par/following-sibling::w:p[1]"/>
                <xsl:with-param name="levelPrevious" select="$level"/>
            </xsl:call-template>
            <xsl:call-template name="grouping">
                <xsl:with-param name="par" select="$par/following-sibling::w:p[2]"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:if test="$par/following-sibling::w:p[1]">
                <xsl:call-template name="grouping">
                    <xsl:with-param name="par" select="$par/following-sibling::w:p[1]"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template name="order">
    <xsl:param name="par"/>
    <xsl:param name="levelPrevious"/>
    <xsl:choose>
        <xsl:when test="$par/w:pPr/w:numPr/w:ilvl/@w:val > $levelPrevious">
            <ol>
                <li>
                    <xsl:value-of select="$par/w:r/w:t"/>
                </li>
                <xsl:call-template name="grouping">
                    <xsl:with-param name="par" select="$par/following-sibling::w:p[1]"/>
                </xsl:call-template>
            </ol>
        </xsl:when>
        <xsl:otherwise>
                <li>
                    <xsl:value-of select="$par/w:r/w:t"/>
                </li>
        </xsl:otherwise>
        </xsl:choose>
</xsl:template>

结果是:

1.First Item
2.Second Item
3.Third Item
   1.Third Item – One
   2.Third Item – Two
       1.Sample Item A
       2.Sample Item B
       3.Fo u rth Item
   3.Sample Item B
   4.Fo u rth Item
4.Third Item – Two
   1.Sample Item A
   2.Sample Item B
   3.Fo u rth Item
5.Sample Item B
6.Fo u rth Item

预期结果是:

1.First Item
2.Second Item
3.Third Item
       a.Third Item – One
       b.Third Item – Two
          I.Sample Item A
          II.Sample Item B
4.Fourth Item

问题是我不知道如何将 4.item 添加到第一组中,而第三项也在其他级别进行迭代。我该如何解决这个问题?

*编辑:我几乎只需要在第四项之后摆脱这个复制的元素!

【问题讨论】:

  • 请显示源 XML 和 完整 XSLT 以便我们能够重现。
  • 几乎不可能将整个代码放在这里。我想了解的是递归函数是如何工作的。在这种情况下,我正在做一些非常愚蠢的事情,看不到它是什么。我不知道我是否可以将文件上传到其他网站并在这里分享。
  • 通常 XSLT 脚本不会那么长,我们只需要一个示例源 XML。您可以尝试使用 pastebin 或 GitHub gists 转储代码/数据。
  • 好的,我编辑了 XSLT 并添加了来自 DOCX 的示例 XML 文件。
  • 我尝试了一个解决方案,但真正困难的是确定嵌套列表项,因为它们的原始结构都是同一级别的&lt;w:p&gt; 标签。在这里,在这个伪数据文件中,它说 First ItemSecond Item、...但没有指示 Third Item - One i> 或 Sample Item 被嵌套。如何确定嵌套项?

标签: xml xslt


【解决方案1】:

考虑这个使用递归模板的 XSLT 1.0 解决方案。请注意,您的 XML 输入并未完全完成,因为未包含非常重要的顶级标签和命名空间 URI。下面的 XSLT 假定以下 XML 结构。如果实际的 XML 仍然不同,当然要相应地更改相应的 XSLT 引用。

XML

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
    <!-- repeat <w:p> tags -->
    </w:body>
</w:document>

XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                              exclude-result-prefixes="w">
 <xsl:output method="html" doctype-system="about:legacy-compat" indent="yes"/> 
 <xsl:strip-space elements="*"/>

   <xsl:template match="/w:document/w:body">
      <html>
          <head>
              <title/>
          </head>
          <body>
            <ol>
               <xsl:apply-templates select="w:p[w:pPr/w:numPr/w:ilvl/@w:val='1']"/>
            </ol>
          </body>
     </html>
   </xsl:template>

   <xsl:template match="w:p">
      <li><xsl:apply-templates select="w:r"/></li>                
      <xsl:call-template name="nest">
         <xsl:with-param name="type" select="'a'"/>
         <xsl:with-param name="par" select="2"/>
         <xsl:with-param name="val" select="following-sibling::*"/>             
      </xsl:call-template>
   </xsl:template>

   <xsl:template name="nest">
      <xsl:param name="type"/>
      <xsl:param name="par"/>
      <xsl:param name="val"/>

      <xsl:if test="$val[1]/w:pPr/w:numPr/w:ilvl/@w:val=$par">
         <ol type="{$type}">
            <xsl:for-each select="$val">
               <xsl:if test="w:pPr/w:numPr/w:ilvl/@w:val=$par">
                  <li><xsl:apply-templates select="w:r"/></li>                  
                  <xsl:call-template name="nest">
                     <xsl:with-param name="type" select="'I'"/>
                     <xsl:with-param name="par" select="$par+1"/>
                     <xsl:with-param name="val" select="following-sibling::*"/>
                  </xsl:call-template>
               </xsl:if>
            </xsl:for-each>
         </ol>
      </xsl:if>
   </xsl:template>

</xsl:stylesheet>

HTML输出

<!DOCTYPE html SYSTEM "about:legacy-compat">
<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title></title>
  </head>
  <body>
    <ol>
      <li>First Item</li>
      <li>Second Item</li>
      <li>Third Item</li>
      <ol type="a">
        <li>Third Item - One</li>
        <li>Third Item - Two</li>
        <ol type="I">
          <li>Sample Item A</li>
          <li>Sample Item A</li>
        </ol>
      </ol>
      <li>Fourth Item</li>
    </ol>
  </body>
</html>

【讨论】:

  • 它正在工作,谢谢,但是当我将它添加到我的代码时它不是。我今天会尝试解决问题,但代码本身正在工作。非常感谢。非常感谢 :)
  • 太棒了!同样,您的实际 XML 可能与我测试的版本(即根/命名空间)不同。如果您遇到问题,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多