我有几个结构类似的XML文件。需要使用XSLT将这些文件合并为一个文件,如下所示。
01.xml (报告编号1,两组-“本地”和"Web")
<Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN1>
<Data Kods="10011">
<A-1>22</A-1>
<A-2>33</A-2>
<A-3>44</A-3>
</Data>
</ReportN1>
</Group>
<Group name="Web">
<ReportN1>
<Data Kods="10011">
<A-1>55</A-1>
<A-2>66</A-2>
<A-3>77</A-3>
</Data>
</ReportN1>
</Group>
</Month>
</Year>
</Reports>02.xml (报告第2号,两组-“本地”和“Web”)
<Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN2>
<Data Kods="10022">
<B-1>33</B-1>
<B-2>44</B-2>
<B-3>55</B-3>
</Data>
</ReportN2>
</Group>
<Group name="Web">
<ReportN2>
<Data Kods="10022">
<B-1>66</B-1>
<B-2>77</B-2>
<B-3>88</B-3>
</Data>
</ReportN2>
</Group>
</Month>
</Year>
</Reports>03.xml (报告第3号,两组-“本地”和"Web")
<Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN3>
<Data Kods="10033">
<C-1>44</C-1>
<C-2>55</C-2>
<C-3>66</C-3>
</Data>
</ReportN3>
</Group>
<Group name="Web">
<ReportN3>
<Data Kods="10033">
<C-1>77</C-1>
<C-2>88</C-2>
<C-3>99</C-3>
</Data>
</ReportN3>
</Group>
</Month>
</Year>
</Reports>分组的预期结果:
<Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN1>
<Data Kods="10011">
<A-1>22</A-1>
<A-2>33</A-2>
<A-3>44</A-3>
</Data>
</ReportN1>
<ReportN2>
<Data Kods="10022">
<B-1>33</B-1>
<B-2>44</B-2>
<B-3>55</B-3>
</Data>
</ReportN2>
<ReportN3>
<Data Kods="10033">
<C-1>44</C-1>
<C-2>55</C-2>
<C-3>66</C-3>
</Data>
</ReportN3>
</Group>
<Group name="Web">
<ReportN1>
<Data Kods="10011">
<A-1>55</A-1>
<A-2>66</A-2>
<A-3>77</A-3>
</Data>
</ReportN1>
<ReportN2>
<Data Kods="10022">
<B-1>66</B-1>
<B-2>77</B-2>
<B-3>88</B-3>
</Data>
</ReportN2>
<ReportN3>
<Data Kods="10033">
<C-1>77</C-1>
<C-2>88</C-2>
<C-3>99</C-3>
</Data>
</ReportN3>
</Group>
</Month>
</Year>
</Reports>发布于 2019-09-11 22:04:25
也许你可以详细说明问题的确切原因是什么?是关于阅读文档的吗?为此,请使用document()。
我将:-将元素的所有后代存储在$group_{name}中-对变量中的项进行分组-为新文档创建一个结构-使用<xsl:copy-of>或<xsl:sequence>输出变量所属的值
例如,
将元素ReportN1存储在变量中:
<xsl:variable name="xml_01_local-r1" select="document('01.xml')//group[@name='local']/ReportN1"/>稍后输出如下所示
<Group name="Local">
<xsl:copy-of select="$xml_01_local-r1"/>
</Group>当然,应该有更有效的方法来做到这一点,但这一种方法将会奏效。
发布于 2019-09-11 23:13:43
如果您知道您正好有三个文档,您可以使用doc函数(例如<xsl:param name="doc1" select="doc('01.xml')"/>)将它们作为三个单独的参数加载,然后这就是一个嵌套分组的问题,下面是一个XSLT3(受Saxon9.8和更高版本支持)示例,正如我已经用于组合分组键的一个分组:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="doc1"><Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN1>
<Data Kods="10011">
<A-1>22</A-1>
<A-2>33</A-2>
<A-3>44</A-3>
</Data>
</ReportN1>
</Group>
<Group name="Web">
<ReportN1>
<Data Kods="10011">
<A-1>55</A-1>
<A-2>66</A-2>
<A-3>77</A-3>
</Data>
</ReportN1>
</Group>
</Month>
</Year>
</Reports>
</xsl:param>
<xsl:param name="doc2"><Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN2>
<Data Kods="10022">
<B-1>33</B-1>
<B-2>44</B-2>
<B-3>55</B-3>
</Data>
</ReportN2>
</Group>
<Group name="Web">
<ReportN2>
<Data Kods="10022">
<B-1>66</B-1>
<B-2>77</B-2>
<B-3>88</B-3>
</Data>
</ReportN2>
</Group>
</Month>
</Year>
</Reports></xsl:param>
<xsl:param name="doc3">
<Reports>
<Year Year="2019">
<Month mon1="1" mon2="12">
<Group name="Local">
<ReportN3>
<Data Kods="10033">
<C-1>44</C-1>
<C-2>55</C-2>
<C-3>66</C-3>
</Data>
</ReportN3>
</Group>
<Group name="Web">
<ReportN3>
<Data Kods="10033">
<C-1>77</C-1>
<C-2>88</C-2>
<C-3>99</C-3>
</Data>
</ReportN3>
</Group>
</Month>
</Year>
</Reports>
</xsl:param>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/" name="xsl:initial-template">
<Report>
<xsl:for-each-group select="$doc1/*/Year, $doc2/*/Year, $doc3/*/Year" group-by="@Year">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="current-group()/Month" composite="yes" group-by="@mon1, @mon2">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="current-group()/Group" group-by="@name">
<xsl:copy>
<xsl:copy-of select="@*, current-group()!*"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</Report>
</xsl:template>
</xsl:stylesheet>https://xsltfiddle.liberty-development.net/pPJ8LUU
在这里,我已经内联了示例XML数据,当然,您也可以使用doc函数加载它们,或者通常在Saxon9中使用collection函数,例如<xsl:param name="docs" select="collection('?select=*.xml')"/>来加载几个文档。然后将<xsl:for-each-group select="$doc1/*/Year, $doc2/*/Year, $doc3/*/Year" group-by="@Year">替换为<xsl:for-each-group select="$docs!*!Year" group-by="@Year">。
对于XSLT2,您可以在第二个分组上不使用composite属性,但是group-by="concat(@mon1, '|', @mon2)"和!也不可用,所以如果顺序很重要,那么使用select="for $doc in $docs return $doc/*/Year"而不是select="$docs!*!Year"。
我假设样式表与虚拟输入文档一起使用,或者使用-it作为Saxon9.8和更高版本的命令行选项,如果使用旧版本,这将是另一个需要更改的地方,我认为XSLT2不允许使用<xsl:template match="/" name="xsl:initial-template">,因此您需要使用一个不同的名称,如<xsl:template match="/" name="main">,并使用-it:main启动Saxon。
https://stackoverflow.com/questions/57890184
复制相似问题