2

我正在尝试将一本大型 XML 书分成多个文件(按章节)。此沙箱 XML:

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <chapter id='1'>Chapter 1</chapter>
        <p>Highly random content.</p>
        <div>foo</div>
        <blockquote>Bar</blockquote>
    <chapter id='2'>Chapter 2</chapter>
        <div>
          <p>p in <i>italicized div</i>!</p>
        </div>
        <p>Content.</p>
    <chapter id='3'>Chapter 3</chapter>
       <blockquote>foo</blockquote>
       <p>foo</p>
    <chapter id='4'>Chapter 4</chapter>
       <p>foo</p>
      <p>end of book</p>
</book>

根据此 XSLT 的需要进行转换:

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>    
<xsl:template match="book">
    <xsl:for-each-group select="*" group-starting-with="chapter"> 
        <xsl:result-document href="{concat('/home/paul/t',@id,'.xhtml')}">
            <xsl:for-each select="current-group()[self::*]">
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:result-document>
    </xsl:for-each-group>
</xsl:template>

问题。当我将 XSLT 应用于更复杂的生产文档时,它不起作用。我会把源文档放在这里..但是它太大了,客户可能不喜欢这样。

我很困惑为什么它不起作用。它不像沙盒测试那样每章制作一个文件,而是制作一个大文件。怀疑问题可能与@id文件名中的 . 在生产文档上,@id出现空值。结果文件名t.xhtml与其中的整本书一样出现,当我真的想要多个t --id of the chapter-- .xhtml.

任何提示在哪里看?有没有一种方法可以使上面的代码对不同的文档复杂性更具弹性(我认为这是我的问题......从简单概念到生产的转变引入了一些我没有抓住的东西,也许一些更严格的代码会有所帮助) .

4

2 回答 2

1

至于您关于如何使您的代码更具弹性的问题,您可以尝试检查输入文件中最明显的错误,这将使您的 XSLT 进程遇到错误或至少产生不可用的输出:

  • 在第一个之前检查其他标签<chapter>
  • 检查<chapter>@id
  • 检查<chapter>具有非唯一性的 's@id

以下 XSLT 将执行这些检查并发出警告。否则它将产生输出文件。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

    <xsl:strip-space elements="*"/>    

    <xsl:template match="book">

      <xsl:variable name="chapter_ids" >
        <xsl:for-each-group select="chapter" group-by="@id">
          <count_me/>
        </xsl:for-each-group>
      </xsl:variable>

      <xsl:choose>

        <xsl:when test="name(*[1]) != 'chapter'">
          <xsl:message>The book does not start with chapter! --- Aborting</xsl:message>
        </xsl:when>

        <xsl:when test="count(chapter[normalize-space(@id) = '']) > 0">
          <xsl:message>The book contains chapters without chapter ids! - Aborting</xsl:message>
        </xsl:when>

        <xsl:when test="count(chapter) &gt; count($chapter_ids/count_me)">
          <xsl:message>The book has more chapters (<xsl:value-of select="count(chapter)"/>) than chapter ids (<xsl:value-of select="count($chapter_ids/count_me)"/>)! - Aborting</xsl:message>
        </xsl:when>

        <xsl:otherwise>

          <xsl:for-each-group select="*" group-starting-with="chapter"> 
            <xsl:result-document href="{concat('./t',@id,'.xhtml')}">
              <xsl:for-each select="current-group()[self::*]">
                <xsl:copy-of select="."/>
              </xsl:for-each>
            </xsl:result-document>
          </xsl:for-each-group>

        </xsl:otherwise>

      </xsl:choose>

    </xsl:template>
</xsl:stylesheet>
于 2013-10-28T18:28:26.913 回答
0

您遇到的行为表明 XPathgroup-starting-with="chapter"没有选择任何内容。我相信真实的内容包含标签名称的差异。将单词修改为chapter任意文字可使问题在示例数据上重现。

于 2013-10-28T16:07:37.290 回答