[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] short and long empty xml elements


Subject: Re: [xsl] short and long empty xml elements
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Mon, 16 Oct 2006 15:05:04 +0200

Stephan Kahnt wrote:
Am Freitag, 13. Oktober 2006 12:49 schrieb Andrew Welch:
On 10/13/06, Stephan Kahnt <stephan.kahnt@xxxxxxxxxx> wrote:
Hi List,

a need to create a xml document that does not contain short empty
elements like <a/> but instead like this <a></a>. I know this is the
same, but the parser of the target system does not recognize the first
version. I use xalan or saxon. Is there a way to control the kind of
output in XSLT ? Currently I run a sed command to replace the first by
the second version.
You can insert comments into the result to prevent tag minimisation,
or use the XHTML output method XSLT 2.0 (you can use this with a 1.0
stylesheet).

Thank you. I will try this.




Hi Stephan,

Did it work out with the comments?
I was thinking today alongside some other option that you might want to try, if you want to do this using purely XSLT 2.0. There's an instruction, <xsl:character-maps> which you can use to achieve your goal.


The other day I wanted output as XML, but needed to intersperse it with <br> (no closing tag) and found a simple resolution for it in XSLT. This, no question, violates the soul of XML, and a while later I convinced people at the other side of the table to go with <br /> (it appeared a minor fix). Nevertheless, here's what I found if you want to go that way with your empty tags:

I assume there's a place in the code where you can test for the tag ending up empty, or you can apply micro-pipelining (term by Wendell Piez?). Here's a sample that is standalone, to illustrate it what I mean with using character maps:

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

<xsl:output method="xml" indent="yes" use-character-maps="empty-a"/>
<xsl:character-map name="empty-a">
<!-- declare a char from priv. use area, to map to 'long' tag version of a-tag -->
<xsl:output-character character="&#xE0F0;" string="&lt;a>&lt;/a>"/>
</xsl:character-map>


   <xsl:template match="tag[normalize-space()]" mode="a" >
      <a>
          <xsl:value-of select="." />
      </a>
   </xsl:template>

<xsl:template match="tag[not(normalize-space())]" mode="a" >
<xsl:text>&#xE0F0;</xsl:text>
</xsl:template>
<xsl:template match="/" name="main" >
<xsl:variable name="test-a">
<tag>with content</tag>
<tag></tag>
</xsl:variable>
<xsl:apply-templates select="$test-a/tag" mode="a"/>
</xsl:template>
</xsl:stylesheet>


This will output the following when used with Saxon 8:
<a>with content</a><a></a>


I recommend you to use characters from the private use area U+E000 - U+F8FF (you may also decide to use Plane-1 and Plane-16, I believe). This is to be sure not to mix up with normal unicode characters. In addition, you may decide to add readability by applying some <!ENTITY xxx yyy> references to your header, using easier mnemonics with character entities.


You will have to do this for every element that may become empty. So, a micro-pipeline may really be the best option here. Be careful, you can really mess up XML with this, making it totally illegal.

HtH,

Cheers,
-- Abel Braaksma
   http://www.nuntia.com


Current Thread
Keywords