首页 > 解决方案 > An XSL file that processes several XML files

问题描述

I need an XSL file that reads several XML files and applies the same transformation to each. So far I've got this (sanitized version):

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

<xsl:template match="document('first_xml_file.xml')">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="//outer_tag/inner_tag">
  ...stuff to appear in output for each file...
  <xsl:for-each select="outer_tag/inner_tag">
    ...stuff to appear in output for each inner_tag...
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet> 

The strategy being that once it works I can add more <template> blocks to process more files.

Because a transformation tool always wants an XML file to work on, I created an empty XML file:

<?xml version="1.0"?>
<nothing/>

Then I ran Microsoft's transformation tool and got:

C:\...>msxsl empty.xml my_style_sheet.xsl

Error occurred while compiling stylesheet 'my_style_sheet.xsl'.

Code:   0x80004005
NodeTest expected here.

-->document<--('first_xml_file.xml')
C:...>

I looked this up and found that the only functions allowed in a pattern are id() and key(). That precludes the use of document() -- and makes it impossible to write an XSL file that reads several XML files, at least the way I want to do it. What is the solution here?

标签: xmlxslt

解决方案


通常的(至少在 XSLT 1 中)和工作方法是match="/*"使用您的原始输入,然后使用<xsl:apply-templates select="document('doc1.xml') | document('doc2.xml') | document('doc3.xml')"/>或将主要输入作为具有辅助 XML 文件 url 的源,然后您将在其中使用<xsl:apply-templates select="document(files/file)"/>例如<files><file>doc1.xml</file><file>doc2.xml</file><file>doc3.xml</file></files>作为内容主要输入。

然后,您将编写与那些引用文件中的元素匹配的模板,而不是在任何文档节点上进行匹配。唯一的问题是您可能需要使用模式来确保您可以区分主文档的根节点或根元素和辅助文档的根或元素。这取决于文档的结构和模板的组织。

一般来说,您的两种匹配模式似乎都很不寻常,match="//outer_tag/inner_tag"也可以缩短为match="outer_tag/inner_tag"不产生任何语义差异。

并且match="document('first_xml_file.xml')"可能会写成match="document-node()[. is document('first_xml_file.xml')]"您的目标是真正识别该特定文档。无论如何,该语法是 XSLT 2,因此它对 MSXML 没有帮助。

XSLT 2/3 更加灵活和强大,无论是在匹配模式的可能性方面,还是通过使用collection和/或之类的函数uri-collection。XSLT 2 或 3 可在 Windows 上通过使用 Saxon 9 HE 的 Java 或 .NET 版本的命令行获得。


推荐阅读