如何使用XSLT连接多个XML文件?

如何使用XSLT连接多个XML文件?,xml,xslt,Xml,Xslt,我有几个结构类似的XML文件。需要使用XSLT将这些文件合并为一个文件,并按如下所示分组 01.xml(报告编号1,两组-“本地”和“网络”) 22 33 44 55 66 77 02.xml(报告编号2,两组-“本地”和“网络”)) 33 44 55 66 77 88 03.xml(报告编号3,两组-“本地”和“网络”) 44 55 66 77 88 99 分组的预期结果: <Reports> <Year Year="2019"> <

我有几个结构类似的XML文件。需要使用XSLT将这些文件合并为一个文件,并按如下所示分组

01.xml(报告编号1,两组-“本地”和“网络”)


22
33
44
55
66
77
02.xml(报告编号2,两组-“本地”和“网络”))


33
44
55
66
77
88
03.xml(报告编号3,两组-“本地”和“网络”)


44
55
66
77
88
99
分组的预期结果:

<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>

22
33
44
33
44
55
44
55
66
55
66
77
66
77
88
77
88
99

也许您可以指定确切的问题是什么?是关于阅读文件吗?用于此

我想: -将元素的所有子体存储在
$group{name}
-将变量中的项目分组 -为新文档创建一个结构 -使用
输出变量所属的值

比如说,

将元素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>


当然,应该有更有效的方法来实现这一点,但这一种会起作用。

如果您知道您正好有三个文档,您可以使用
doc
函数(例如
)将它们作为三个单独的参数加载,然后这只是一个嵌套分组的问题,下面是一个XSLT 3(由Saxon 9.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>

在这里,我内联了示例XML数据,但您当然也可以使用
doc
函数加载它们,或者通常使用Saxon 9的
collection
函数加载多个文档。然后将
替换为

对于XSLT 2,您将在第二个分组上使用no
composite
属性,然后使用
groupby=“concat(@mon1,|,@mon2)”
也不可用,因此如果订单重要,则使用
select=“for$doc in$docs return$doc/*/Year”
而不是
select=“$docs!*!Year”


我假设样式表与虚拟输入文档一起使用,或者与
-it
一起用作Saxon 9.8及更高版本的命令行选项,如果使用较旧版本,这将是您需要的另一个更改,我认为XSLT2不允许
,因此您需要使用不同的名称,如
,并使用
-it:main

启动Saxon,您使用哪个XSLT版本,哪个XSLT处理器?这似乎只是一个分组问题,或者,如果您使用XSLT 3,可能是
xsl:merge
的一个用例。可能是Martin的重复,我使用Saxon XSLT处理器,XSLT版本2.0OS-50101,我在xsl转换方面没有太大的过期性,您能给我一些示例吗?谢谢您的详细回答,Martin。这很有效!
<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>
<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>