开发者

xslt help - remove empty tags and replaces * with empty tags

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 xs开发者_如何学编程lt :

  <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.


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>


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜