from document I am trying to use XSLT which copies most of the tags, but removes the empty " " tags . That is, ...">

How to remove <b / "> from document

I am trying to use XSLT which copies most of the tags, but removes the empty " <b/>

" tags . That is, it should copy like " <b> </b>

" or " <b>toto</b>

", but completely remove " <b/>

".

I think the template would look like this:

<xsl:template match="b">
  <xsl:if test=".hasChildren()">
    <xsl:element name="b">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:if>
</xsl:template>

      

But of course the " hasChildren()

" part doesn't exist ... Any idea?

+1


source to share


7 replies


I wonder if this will work?



<xsl:template match="b">
  <xsl:if test="b/text()">
    ...

      

+2


source


dsteinweg put me on the right track ... I ended up with:



<xsl:template match="b">
    <xsl:if test="./* or ./text()">
        <xsl:element name="b">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:if>
</xsl:template>

      

+3


source


This transformation ignores any <b> elements that do not have a child node. A node in this context means an element, text, comment, or processing instruction node.

<xsl: stylesheet version = "1.0"
 xmlns: xsl = "http://www.w3.org/1999/XSL/Transform">
 <xsl: output omit-xml-declaration = "yes" />
    <xsl: template match = "node () | @ *">
      <xsl: copy>
         <xsl: apply-templates select = "node () | @ *" />
      </ xsl: copy>
    </ xsl: template>

    <xsl: template match = "b [not (node ​​()]" />
</ xsl: stylesheet>

Note that we are using one of the most fundamental XSLT design patterns here - using identity transformation and overriding it for specific nodes.

The overriding template will only be selected for nodes that are elements named "b" and do not have (any nodes like) children. This template is empty (has no content), so the effect of its application is that the corresponding node is ignored / discarded and not reproduced in the output.

This method is very efficient and is widely used for such tasks, as well as for renaming, changing content or attributes, adding children or siblings to any specific node that can be matched (any node type excluding the namespace node can be used as a match pattern in the "match" attribute in <xsl: template / ">

Hope it helped.

Greetings,

Dimitar Novachev

+3


source


See if this will work.

<xsl:template match="b">
  <xsl:if test=".!=''">
    <xsl:element name="b">
     <xsl:apply-templates/>
    </xsl:element>
  </xsl:if>
</xsl:template>

      

+1


source


An alternative might be the following:

<xsl:template match="b[not(text())]" />

<xsl:template match="b">
  <b>
    <xsl:apply-templates/>
  </b>
</xsl:template>

      

+1


source


You can put all the logic in a predicate and adjust the template to match only what you want and remove it:

<xsl:template match="b[not(node())] />

      

This assumes that you have an identification pattern later in the transformation that sounds like you. This will automatically copy the "b" tags with the content you want:

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

      

Edit: Now uses node () just like Dimitri below.

+1


source


If you have access to update the original XML you can try using xml: space = preserve on the root element

<html xml:space="preserve">
...
</html>

      

This way, the space in the blank <b> </ l; / b> tag is preserved and therefore can be distinguished from the <b /> in XSLT.

<xsl:template match="b">
   <xsl:if test="text() != ''">
   ....
   </xsl:if>
</xsl:template>

      

0


source







All Articles