我有几个包含TEI历史字母的单个XML文件。现在我想将它们合并为一个文件,并以日期作为标准。
A1.xml
| Full Path | File |
|:------------------------:|:---------:|
| C:/Path/to/the/file1.ext | file1.ext |
| C:/Path/to/the/file2.ext | file2.ext |
| C:/Path/to/the/file3.ext | file3.ext |
| C:/Path/to/the/file4.ext | file4.ext |
和第二个文件,A2.xml:
| Full Path | File |
|:------------------------:|:---------:|
| C:\Path\to\the\file1.ext | file1.ext |
| C:\Path/to\the\file2.ext | file2.ext |
| C:\Path/to\the\file3.ext | file3.ext |
| C:\Path/to\the\file4.ext | file4.ext |
和第三个,A3.xml:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xml:id="1">
<teiHeader>
<title>Letter 1</title>
<date when="19990202" n="0"></date>
</teiHeader>
<text>
<p>Content of letter 1</p>
</text>
</TEI>
文件以连续的文件名命名&#34; A001.xml&#34;至&#34; A999.xml&#34;,但未达到所需的顺序。所以我的首选输出将是单个文件letters.xml:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xml:id="2">
<teiHeader>
<title>Letter 1</title>
<date when="20010202" n="0"></date>
</teiHeader>
<text>
<p>Content of letter 2</p>
</text>
</TEI>
即使我找到了将多个XML文件合并为一个的方法,但我还是设法使用排序标准让它工作。这甚至可能吗?
答案 0 :(得分:5)
这甚至可能吗?
XSLT旨在能够使用XML执行任何转换任务,并且被认为是图灵完备所以是的,确实可能。
我将假设XSLT 3.0,因为这是展示该版本新功能的一个很好的例子:xsl:merge
。并不是说它不可能,但它并不是那么简单。它专门设计用于外部源,但可以使用任何输入,甚至任何大小(它是可流动的)。
xsl:merge
示例使用上面的示例,以下代码将按该文件模式获取所有XML文件,并创建一个文件,其中包含按日期排序的每个文档的副本。
<!-- xsl:initial-template, new in XSLT 3.0 is like "int main()" in C-style languages -->
<xsl:template name="xsl:initial-template">
<!-- your other code here -->
<result>
<xsl:merge>
<!--
xsl:merge defines the source for merging. It is quite powerful. Here
is a simple example with your data.
With for-each-item you select a sequence of items that need to be merged,
which goes in two steps, first you select a list of anchor items, then
you use the select-attribute to select the sequence you want to merge. Here
a collection of documents is requested, like in OP's question
The select statement selects, with focus on each document, the sequence
of items to be merged. This sequence can be of any length (here it selects all
historic letters)
The merge-key defines the key for which items in the merge sequence are sorted,
an incorrect order will result in an error, unless sort-before-merge
is also specified.
-->
<xsl:merge-source
for-each-item="collection('files/A*.xml')"
select="/root/historic-letter/tei:TEI"
sort-before-merge="true">
<xsl:merge-key
select="tei:teiHeader/tei:data/tei:when"
order="descending"
data-type="number" />
</xsl:merge-source>
<!-- the merge action is called for each item resulting from the select
statement above. Only in this place can you use current-merge-key()
and the current-merge-group() functions, which work similar to their grouping
counterparts.
-->
<xsl:merge-action>
<source original-document="{base-uri()}">
<xsl:copy-of select="." />
</source>
</xsl:merge-action>
</xsl:merge>
</result>
</xsl:template>
答案 1 :(得分:1)
由于您只想将XML文档与Saxon 9和XSLT 2.0连接起来,它就像
一样简单<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:param name="file-suffix" as="xs:string" select="'A*.xml'"/>
<xsl:template match="/" name="main">
<CORRESPONDENCE>
<xsl:perform-sort select="collection(concat('.?select=', $file-suffix))/*">
<xsl:sort select="teiHeader/date/xs:integer(@when)"/>
</xsl:perform-sort>
</CORRESPONDENCE>
</xsl:template>
</xsl:stylesheet>
您可以使用命令行选项-it:main -xsl:stylesheet.xsl
或者如果需要使用主输入文档来运行它,但是只需使用collection
获取要处理的文档,如图所示。
如果输入样本中的元素位于命名空间http://www.tei-c.org/ns/1.0
中,正如Abel所评论的那样,那么您需要将代码更改为
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="xs"
version="2.0">
<xsl:param name="file-suffix" as="xs:string" select="'A*.xml'"/>
<xsl:template match="/" name="main">
<CORRESPONDENCE>
<xsl:perform-sort select="collection(concat('.?select=', $file-suffix))/*">
<xsl:sort select="teiHeader/date/xs:integer(@when)"/>
</xsl:perform-sort>
</CORRESPONDENCE>
</xsl:template>
</xsl:stylesheet>