如何最好地组合文档以进行 XSLT 处理?

How best to combine documents for XSLT processing?

我有一堆单独编辑和转换(xml -> xsl-fo)以创建 pdf 文件的报告。此外,我想将所有报告合并到一本书中,以便使用单个转换创建。我想我可以为此使用 document() 函数:

(个别报道是这样的):

<?xml version="1.0"?>
<!DOCTYPE blue_book SYSTEM "../DTD/blue_book.dtd">
<blue_book>

  ~~stuff~~

</blue_book>

我创建了一个名为 reports.xml:

的占位符文件
<?xml version="1.0"?>
<reports>
  <report filename="title.xml"/>
  <report filename="preface.xml"/>
  <report filename="report1.xml"/>
  <report filename="report2.xml"/>
  <report filename="report3.xml"/>
  <report filename="report4.xml"/>
</reports>

然后在我的样式表中使用类似这样的东西来处理它们:

<xsl:for-each select="/reports/report">
  <xsl:apply-templates select="document(@filename)/blue_book"/>
</xsl:for-each>

这种方法可行,但我创建的所有用于开始页码编号和基于文档中的位置自动生成 id 以用于链接目的的代码都分崩离析。例如,我希望页码从第 3 份报告开始。如果我只是将所有 xml 文件合并到一个文件中,则以下工作正常。

<xsl:template match="blue_book">
  <xsl:choose>
    <xsl:when test="count(preceding-sibling::blue_book) &lt; 2">
      <fo:page-sequence master-reference="front-matter">
        <fo:flow flow-name="xsl-region-body">
          <xsl:apply-templates/>
        </fo:flow>
      </fo:page-sequence>
    </xsl:when>

    <xsl:when test="count(preceding-sibling::blue_book) = 2">
      <fo:page-sequence master-reference="report">
        <xsl:attribute name="initial-page-number">1</xsl:attribute>

        <fo:static-content flow-name="first-xsl-region-before">
            <xsl:if test="lead_para">
              <fo:block font-variant="small-caps" text-align="center">
                <xsl:value-of select="lead_para"/></fo:block>
            </xsl:if>
          <fo:block>&#x00A0;</fo:block>
        </fo:static-content>
(etc. -- lots of xsl-fo)

但是当使用document()函数加载文件时,preceding-sibling count似乎总是0;即它只查看该特定报告,而不考虑之前加载的报告。

这很有道理,但没有解决我的问题。有没有标准的方法来做到这一点?特别是,我想处理所有报告 就好像它们在同一个 XML 文档 中一样,但不必实际将它们实际连接在一起。*

*如果有人想知道为什么,那是因为编辑们想单独维护和编辑报告,但仍然能够通过 AH Formatter 运行 一些东西,这给了他们完整的书。文件串联超出了他们的技能范围。

嗯,如果确实需要,可以建一个复合文档:

<xsl:variable name="composite">
 <composite>
   <xsl:for-each select="/reports/report">
     <xsl:copy-of select="document(@filename)/blue_book"/>
   </xsl:for-each>
 </composite>
</xsl:variable>

如果您受困于 XSLT 1.0,则需要使用 exslt:node-set($composite) 对此变量进行进一步处理。

为什么不使用实体?只需更改创建占位符文件的方式即可。您问:

"In particular, I'd like to process all the reports as if they were in the same XML document but without having to actually physically concatenate them together."

是的,使用实体。如果我有这个:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE reports [
<!ENTITY title SYSTEM "title.xml">
<!ENTITY document1 SYSTEM "document1.xml">
]>
<reports>
    &title;
    &document1;
</reports>

我 title.xml 是这样的:

<blue_book>
    <title>I am the title of title</title>
</blue_book>

和document1.xml这样:

<blue_book>
    <title>I am the title of document 1</title>
</blue_book>

xpath //reports/blue_book/title 产生:

系统 ID:F:\RenderX\Demonstrations\Tricks\Image\title.xml 说明:我是title of title XPath 位置:/reports[1]/blue_book[1]/title[1] 开始位置:2:5 结束位置:2:43

系统 ID:F:\RenderX\Demonstrations\Tricks\Image\document1.xml 描述:我是文档1的标题 XPath 位置:/reports[1]/blue_book[2]/title[1] 开始位置:2:5 结束位置:2:48

And count(//reports/blue_book) returns "2" 所以我没有测试过,但在我看来你所做的一切都可以在没有 document()

的情况下工作