Solved

XSL to replace  <tag/> with <tag></tag>

Posted on 2008-10-25
5
1,148 Views
Last Modified: 2013-11-18
The requirement is that, all the empty tags in the transformed XML:should look like <tag></tag> and not <tag/>
0
Comment
Question by:creditpointe
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
5 Comments
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 22803093
Forget it, it can't be done in XSLT.

But basically, any application that has a preference, is not a real XML application, it should not make a difference

From the XML point of view <tag/> and <tag></tag> are equivalent,
and the serialisation engine of your XSLT processor can choose one of both options when serialising.
Most choose the short form, it is not documented and even if you would find a processor that does it the way you want, you can't guarantuee that it will not break in the next version

There are a number of non documented things you can try

1. If it is allowed to put something in between the tags, the tags will be broken
This could be a comment, a space or a process instruction
<tag><xsl:comment>*</xsl:comment></tag>
will generate something like this
<tag><!-- * --></tag>
your follow up XML process should ignore that comment and it could have the same effect

2. If it is not allowed to have something in between the tags, use a post process.
I have a customer who built his own XML loader that puts stuff I send him in a database
He has built his own parser and it is crappy, so it doesn't take <tag/>
For him I use this technique
I create <tag><!-- * --></tag>
and in a post process I use regular expressions that simple remove all the <!-- * --> from the document
This works really well

3. There is one obscure technique that helps with some processors. But it is undocumented and I can't guarantuee that it won't break in one of the next versions. Basically you try to throw something in between the two tags that won't get serialised at the end.
This for example works in Xalan (for Java)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:variable name="empty"/>
 <xsl:template match="tag">
     <tag>
         <xsl:value-of select="$empty"/>
     </tag>
 </xsl:template>
</xsl:stylesheet>
I bet you could find similar constructs that would break the tag in Saxon as well... but these are ugly hacks
I used that for a while, but I strongly recommend not to use dirty hacks like this... the will break at some point

So,
first evaluate if you really need this. If there is a real need it would be because the next step in the pipeline is in default.
There should not be a requirement for what you ask with real XML applications
then evaluate whether it is allowed to put a space or a comment in between,
If you can't put a comment or so in between, still do, but remove it with regular expressions in a post process

I hope this helps you

Geert

0
 

Author Comment

by:creditpointe
ID: 22804165
Thanks Gertone for providing so many options.
The first solution is very interesting.
Allow me to ask a few more questions and add something more to my question.

Is there any way which would allow to put an empty space for all the tags (for the complete inbound xml) processed where there is no text? In other words, if the source xml has <tag></tag> (for any tag across the inbound xml) then the output would consist of <tag> "space" </tag>?
0
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 500 total points
ID: 22804347
That largely depends on your stylesheet,
but you could have a template
<xsl:template match="*[string-length(.) = 0]">
  <xsl:copy>
    <xsl:text> </xsl:text>
  </xsl:copy>
</xsl:template>

and add this predicate to all other templates you have
<xsl:template match="myNotEmptyElement">
which then should become
<xsl:template match="myNotEmptyElement[* or string-length(normalize-space(.)) > 0]">
to make sure the element has content before processing starts
0
 

Expert Comment

by:avsviswanath
ID: 24304063
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml"/>
      <xsl:template match="/">
      <xsl:apply-templates select="*"/>
      </xsl:template>

      <xsl:template match="*">
      <xsl:choose>
      <xsl:when test=". != ''">
      <xsl:element name="{name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
      </xsl:element>
      </xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
<xsl:comment>empty element</xsl:comment>
</xsl:element>
</xsl:otherwise>
</xsl:choose>

</xsl:template>

</xsl:stylesheet>
use this it will work.
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 24308143
@avsviswanath

That does not really do what the original poster asked,
and was suggested as the first option in the first comment

I add this just in case someone finding this answer in the database thinks that something new was added, after an answer was accepted
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Preface In the first article: A Better Website Login System (http://www.experts-exchange.com/A_2902.html) I introduced the EE Collaborative Login System and its intended purpose. In this article I will discuss some of the design consideratio…
Browsers only know CSS so your awesome SASS code needs to be translated into normal CSS. Here I'll try to explain what you should aim for in order to take full advantage of SASS.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question