Question

I am having a problem while doing some XSLT pre-processing in my java program. We get an asterisk (*) from a mainframe program when it wants to blank out a value, which my java process has to treat like a blank or empty tag. So we apply an xslt to the input before my jaxb process.

We are applying this xslt :

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no"/>
  <xsl:template match="@*[. = '*']">
    <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
      <xsl:text></xsl:text>
    </xsl:attribute>
  </xsl:template>
  <xsl:template match="*[. = '*']">
    <xsl:copy>
      <xsl:text></xsl:text>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

The above xslt works fine for ALMOST all test cases. Except in the case where there is only ONE sub-element and that happens to be an asterisk.

For instance consider this in the input:

<MYROOT><Address3><Line2>*</Line2><Line3>*</Line3></Address3></MYROOT>

works well. It produces this output:

<MYROOT><Address3><Line2/><Line3/></Address3></MYROOT>

The xml input below, however , produces an incorrect response.

<MYROOT><Address4><PermanentAddress><Line2>*</Line2></PermanentAddress></Address4></MYROOT>

But instead of giving the response as

<MYROOT><Address4><PermanentAddress><Line2></Line2></PermanentAddress></Address4></MYROOT>

It gives this:

<MYROOT/>

Please help. Any help is appreciated as I did not have this test case while testing my code.

Was it helpful?

Solution

That's because . is the inner text, which is a concatenation of all inner text nodes. You need to make sure in your condition that there is no child node either or only a text node with * as contents.

This should work:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>

    <xsl:strip-space elements="*"/>

    <xsl:template match="*[not(*) and (. = '*')] | @*[. = '*']">
        <xsl:copy />
    </xsl:template>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

OTHER TIPS

Replace:

<xsl:template match="*[. = '*']"> 
    <xsl:copy> 
      <xsl:text></xsl:text> 
    </xsl:copy> 
  </xsl:template>

with

  <xsl:template match="*[not(*) and not(text()[2])]/text()[.='*']"/>

This is much more efficient than having to calculate the string value of every element, because the string value of an element is the concatenation of all its descendent text nodes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top