Transforming file compliant with Xml Schema A into a file compliant with XML schema B using XSLT
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 require开发者_StackOverflow中文版s 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.
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
<xsl:template match="element(*, type-name)">
where type-name is the name of a type in the schema.
精彩评论