[xsl] Namespace de-duplication for dynamically generated elements

Subject: [xsl] Namespace de-duplication for dynamically generated elements
From: Ian Stokes-Rees <ijstokes@xxxxxxxxxxxx>
Date: Tue, 09 Sep 2008 02:35:28 -0400
For reasons which I won't bore you with, we have an input XML format of the style:

customer1.xml:
<order xmlns:pt="urn:ex">
   <foo name="pt:zip"> apple </foo>
   <foo name="pt:zap"> orange </foo>
</order>

customer2.xml:
<order xmlns:go="urn:ex">
   <foo name="go:zip"> pear </foo>
   <foo name="go:zap"> banana </foo>
</order>

We want a single XSLT which will handle these without a priori knowledge of the QNames or namespace *inside* the @name attribute. We need to transform these into:

customer1-out-desired.xml:
<output xmlns:pt="urn:ex">
   <pt:zip> apple </pt:zip>
   <pt:zap> orange </pt:zap>
</output>

customer2-out-desired.xml:
<output xmlns:go="urn:ex">
   <go:zip> pear </go:zip>
   <go:zap> banana </go:zap>
</output>

After a long struggle, I've managed some hacky XSLT which manages the namespace mapping from strings and NS declarations to prefixed QName elements, however I end up getting the xmlns:pt="urn:ex" element on *every* leaf element (e.g. <go:zip xmlns:go="urn:ex">), rather than just once on the document element as I would like it:


customer1-out-actual.xml: <output> <pt:zip xmlns:pt="urn:ex"> apple </pt:zip> <pt:zap xmlns:pt="urn:ex"> orange </pt:zap> </output>

customer2-out-actual.xml:
<output>
   <go:zip xmlns:go="urn:ex"> pear </go:zip>
   <go:zap xmlns:go="urn:ex"> banana </go:zap>
</output>

Does anyone know of any tricks to avoid this situation?

Cheers,

Ian

PS - The relevant XSLT snippet I've written is:

 <xsl:template match="foo">
   <xsl:element name="{substring-after(@name,':')}"
     namespace="{namespace-uri-for-prefix(substring-before(@name,':'),.)}">
      <xsl:value-of select=".">
   </xsl:element>
   </xsl:template>

--
Ian.Stokes-Rees@xxxxxxxxxxxx +1 (617) 418-4168
SP Metric Limited, Technology Consulting

Current Thread