如何最好地组合文档以进行 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) < 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> </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()
的情况下工作
我有一堆单独编辑和转换(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) < 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> </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()
的情况下工作