我有几个具有不同结构的XML文件,我想根据指示日期(@when
)的公共属性以时间轴的形式合并。
<persons>
<person id="p0001">
<name>John Skelton</name>
<born when="1782-05-01">John Skelton born</born>
<died when="1866-01-05">John Skelton died</died>
</person>
...
</persons>
<events>
<event id="e0001" when="1782">
<name>Publication of <hi>Transactions</hi></name>
</event>
<event id="e0002" when="1866">
<name>Boston meeting of Generals</name>
</event>
...
</events>
这些XML文件可能还有更多。
我想要的输出将是:
<div id="timeline">
<div class="year">1782</div>
<p data-when="1782-05-01" data-id="p0001">John Skelton born</p>
<p data-when="1782" data-id="e0001">Publication of <em>Transactions</em></p>
<div class="year">1866</div>
<p data-when="1866-01-05" data-id="p0001">John Skelton died</p>
<p data-when="1866" data-id="e0002">Boston meeting of Generals</p>
</div>
有没有办法在XSLT2中实现这一点:
@when
属性的其他元素我并不太担心输出的实际格式,但我正在努力弄清楚(a)合并,(b)分组,以及(c)排序所涉及的步骤第一名。我已尝试对文档进行分组
<xsl:param name="lookup-documents" select="document('file1.xml'),document('file2.xml')"/>
然后在for-each循环中使用基于dates
的{{1}}键,但我可能完全走错了轨道并且没有真正显示的XSLT。
如果可能的话,我更喜欢“拉”式XSLT2解决方案。非常感谢您提前提供任何帮助!
答案 0 :(得分:0)
我会尝试将文件作为集合提取,然后使用for-each-group
按年份进行分组和排序,然后我将组群推送到模板,以考虑元素的不同结构:< / p>
<?xml version="1.0" encoding="UTF-8"?>
<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="input-pattern" as="xs:string" select="'file*.xml'"/>
<xsl:variable name="input-docs" select="collection(concat('.?select=', $input-pattern))"/>
<xsl:output method="html" indent="yes"/>
<xsl:template name="main">
<div>
<xsl:for-each-group select="$input-docs//*[@when]" group-by="xs:integer(substring(@when, 1, 4))">
<xsl:sort select="current-grouping-key()"></xsl:sort>
<div class="year">
<xsl:value-of select="current-grouping-key()"/>
</div>
<xsl:apply-templates select="current-group()">
<xsl:sort select="@when"/>
</xsl:apply-templates>
</xsl:for-each-group>
</div>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="born | died">
<p data-when="{@when}" data-id="{../@id}">
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="event">
<p data-when="{@when}" data-id="{@id}">
<xsl:apply-templates select="name/node()"/>
</p>
</xsl:template>
<xsl:template match="hi">
<em>
<xsl:apply-templates/>
</em>
</xsl:template>
</xsl:stylesheet>
那样我得到了
<div>
<div class="year">1782</div>
<p data-when="1782" data-id="e0001">Publication of <em>Transactions</em></p>
<p data-when="1782-05-01" data-id="p0001">John Skelton born</p>
<div class="year">1866</div>
<p data-when="1866" data-id="e0002">Boston meeting of Generals</p>
<p data-when="1866-01-05" data-id="p0001">John Skelton died</p>
</div>
您需要更改我猜的群组项目的种类,目前尚不清楚如何确定具有完整日期的项目是否在@when
中只有一年的项目之前结束。
该收集方法是特定于Saxon的(http://saxonica.com/html/documentation9.6/sourcedocs/collections.html),但我认为Altova和XmlPrime具有类似的URI收集语法,允许从模式中读取大量文件。