使用XSL合并和排序多个XML文件

时间:2011-09-05 21:28:20

标签: xml xslt sorting merge multiple-files

问题是使用XSL合并和排序多个XML文件并输出有效的HTML,可以使用Firefox> = 3.5查看,如果可能,IE> = 7。答案应该尽可能简单(表现并不重要)。

文件a.xml

<?xml version="1.0"?>
<root>
    <tag>cc</tag>
    <tag>aa</tag>
</root>

文件b.xml

<?xml version="1.0"?>
<root>
    <tag>xx</tag>
    <tag>bb</tag>
</root>

文件index.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="merge.xslt"?>
<list>
    <entry>a.xml</entry>
    <entry>b.xml</entry>
</list>

文件merge.xslt

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ph="http://ananas.org/2003/tips/photo">

    <xsl:output method="html"/>

    <xsl:template match="list">
        <html>
            <body>
                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="entry">
        <xsl:for-each select="document(.)/root/tag">
            <!-- This will only sort the values of a single file -->
            <xsl:sort select="." data-type="text" order="ascending" />
            - <xsl:value-of select="."/> <br/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

当前输出:

  • AA

  • CC

  • BB

  • XX

预期产出:

  • AA

  • BB

  • CC

  • XX

1 个答案:

答案 0 :(得分:8)

解决方案是一个非常简短的转换(绝对没有扩展功能是必需的!):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <html>
   <ul>
    <xsl:apply-templates
       select="document(entry)/*/tag">
      <xsl:sort/>
    </xsl:apply-templates>
   </ul>
  </html>
 </xsl:template>

 <xsl:template match="tag">
  <li><xsl:value-of select="."/></li>
 </xsl:template>
</xsl:stylesheet>

在提供的 index.xml 文件上应用此转换时

<list>
    <entry>a.xml</entry>
    <entry>b.xml</entry>
</list>

产生了想要的正确结果

<html>
   <ul>
      <li>aa</li>
      <li>bb</li>
      <li>cc</li>
      <li>xx</li>
   </ul>
</html>

并在任何浏览器中显示为

   

          
  • AA
  •       
  • BB
  •       
  • CC
  •       
  • XX
  •    

解释此解决方案使用标准XSLT函数document()的强大功能。如W3C XSLT 1.0建议书中所定义:

  

当文档函数只有一个参数和参数时   是一个节点集,然后结果是union,对于每个节点   参数node-set,调用文档函数的结果   第一个参数是节点的字符串值

这解释了我们的代码

中此片段的效果
<xsl:apply-templates
   select="document(entry)/*/tag">
  <xsl:sort/>
</xsl:apply-templates>

这里发生的是document()函数的参数是entry顶部元素的所有index.xml子节点的节点集。结果是所有文档节点的并集。

<强>因此

select="document(entry)/*/tag"

选择tag中引用的所有文档中的所有index.xml元素。然后对它们进行排序(按xsl:sort),并且已经排序的节点列表的每个元素都由匹配tag的模板处理。