使用 XSLT 将符合 Xml 架构 A 的文件转换为符合 XML 架构 B 的文件
我搜索过这个问题,但似乎很难用语言表达涉及 XSL 的问题,所以我什么也没想到。
我遇到的问题是这样的:
一家公司生产了一个使用 XML 文件来存储其“文档”的应用程序。这些文件是针对架构版本 1.1 强制执行的。
但是,该公司决定发布一个新版本的软件,该版本针对具有不同结构的新架构(架构 1.2)进行验证。
为了让客户无缝地使用新版本,我们希望以编程方式在打开文件时将其 1.1 兼容文件转换为 1.2 兼容文件。理想情况下,我们使用 XSL 转换来完成此操作。
在这两个模式中,某些类型是相同的,某些类型具有新的或重命名的成员,还有一些存储在完全不同的结构中。因此,编写从一种到另一种的转换是相当乏味的,维护它更是如此。
最好编写一种转换生成转换,它可以将旧模式中未更改的类型匹配到新模式,并发出占位符元素(例如
元素) )在无法这样做的地方,以提示开发人员在需要的地方手动编写自定义逻辑,并保证其他地方都兼容。
因此,过程如下:
- 针对架构 1.2 运行转换 A。这会生成变换 B;
- 针对架构 1.1 运行转换 B。这会尽可能将 Schema 1.2 与 Schema 1.1 相匹配,从而生成转换 C;
- 开发人员使用转换 C 作为骨架来编写从实例 1.1 到实例 1.2 的无懈可击的转换。
我已经通过实现这一点找到了一个公平的方法,但是 XSLT 1.0 的一些细节给我带来了问题。
转换 B 需要自动生成
语句,并将遇到的每个元素的类型名称写入 name
属性中。然后,这将正确运行每个类型的转换逻辑,以生成转换C。
但是,call-template
似乎不接受任何xpath语法。它坚持 name
必须仅包含一个 NMTOKEN 和一个 NMTOKEN。我可以从设计的角度理解这一点,但这非常令人恼火,因为我想根据元素的类型而不是其名称在元素上运行逻辑。我想在 xsl:template match="element"
模板内声明 call-template name="@type"
。我的第 1 阶段生成确保存在一个匹配的命名模板可供调用。
我不知道如何继续。以前有人尝试过类似的事情吗?是否有一些计算机科学的基本理论表明它在声明性语法中是不可能的? (我希望不是!)
我希望我的解释很清楚。如果没有的话我会发布代码。
I have searched for this question, but it seems fiendishly hard to express a problem involving XSL in words, so I've come up with nothing.
The problem I have is thus:
A company produces an application which uses XML files to store its 'documents'. These files are enforced against schema version 1.1
However, the company decides to release a new version of the software which validates against a new schema with a different structure, schema 1.2
In order for the customer to seamlessly use the new version, we want to programmatically convert their 1.1-compliant files into 1.2-compliance on file open. Ideally, we do this using an XSL Transformation.
Of the two schemas, some types are identical, some types have new or renamed members, and some are stored in a totally different structure. Therefore writing the transformation from one to the other is quite tedious, and maintaining it even more so.
It would be nice to write a kind of transform-generating transform which can match the unchanged types from the old schema to the new one, and emit placeholder elements (<xsl:message>
elements, for example) wherever it can't do so, in order to prompt the developer to write the custom logic by hand where it's needed, with a guarantee that everywhere else is compliant.
So the procedure goes:
- Run Transform A against Schema 1.2. This generates Transform B;
- Run Transform B against Schema 1.1. This matches Schema 1.2 to Schema 1.1 where possible, producing Transform C;
- Transform C is used as a skeleton by the developer to write a watertight transformation from instance 1.1 to instance 1.2.
I have gotten a fair way through implementing this, but a few particulars of XSLT 1.0 are causing me problems.
Transform B requires automatic generation of <xsl:call-template>
statements with the typename of each element encountered pencilled into the name
attribute. This will then correctly run the transformation logic for each type in order to generate Transform C.
However, call-template
does not seem to accept any xpath syntax whatsoever. It insists that name
must contain an NMTOKEN and an NMTOKEN only. I can understand this from a design point of view but it's quite irritating, because I want to run logic on an element based on its type, not its name. I'd like to state call-template name="@type"
inside an xsl:template match="element"
template. My stage 1 generation ensures that a matching named template will exist to call.
I am not sure how to proceed. Has anybody tried anything like this before? Is there some fundamental theory of computer science which declares that it isn't possible in declarative syntax? (I hope not!)
I hope my explanation is clear. I'll post code if not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,市场上有许多工具试图根据源模式和目标模式生成转换,以及定义它们之间关系的图形工具。就我个人而言,我对这些工具不太满意,但有些人似乎喜欢它们,所以尝试一下。可以在流行的 XML 工具(例如 XML Spy 和 Stylus Studio)中找到示例。
其次,尝试使用 xsl:call-template 来实现此目的似乎很奇怪。显然,这是使用模板规则和 xsl:apply-templates 进行基于规则的转换的情况。基于元素类型的调度机制显然是 apply-templates 而不是 call-template。在 XSLT 2.0 中,您可以直接使用模式感知样式表执行您所要求的操作,该样式表具有以下形式的规则
,其中 type-name 是模式中类型的名称。
Firstly, there are a number of tools on the market that attempt to generate transformations based on a source and target schema, and graphical tools to define the relationship between them. Personally, I've had very little joy with these tools, but some people seem to like them, so give them a try. Examples can be found in popular XML tools such as XML Spy and Stylus Studio.
Secondly, it seems very odd to be trying to use xsl:call-template for this. It's clearly a case for rule-based transformation using template rules and xsl:apply-templates. The mechanism for dispatching based on an element's type is clearly apply-templates rather than call-template. In XSLT 2.0 you can do what you're asking for directly with a schema-aware stylesheet that has rules of the form
where type-name is the name of a type in the schema.