Creating tag only if value exist in source

For example:

<a>
<b>
    <aaa>val</aaa>
    <bbb></bbb>
</b>
</a>

I want an xslt that will create aaa,bbb,ccc tags only if they contain value in source.

Until now i used:

<aaa><xsl:value-of select="//aaa"/></aaa>
<bbb><xsl:value-of select="//bbb"/></bbb>
<ccc><xsl:value-of select="//ccc"/></ccc>

Which is clearly not good.

Answers


Similar to the other answers, this doesn't rely on names or structure; it simply strips elements that do not contain any child elements or text. Like it was previously mentioned, it is difficult to tell what output you're actually looking for.

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

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

</xsl:stylesheet>

Output

<a>
   <b>
      <aaa>val</aaa>
   </b>
</a>

Making some assumptions about what you'd like to achieve (you did not say it so clearly I'm afraid), the solutions below should work.

Input

<a>
  <b>
    <aaa>val</aaa>
    <bbb></bbb>
  </b>
</a>

The stylesheet is very dynamic, i.e. does not rely on the actual element names, but it relies on the structure of an XML document.

Stylesheet ("dynamic")

<?xml version="1.0" encoding="utf-8"?>

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

   <xsl:output method="xml" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="/*|/*/*">
       <xsl:copy>
           <xsl:apply-templates/>
       </xsl:copy>
   </xsl:template>

   <xsl:template match="/*/*/*[not(text())]"/>
   <xsl:template match="/*/*/*[text()]">
       <xsl:copy-of select="."/>
   </xsl:template>

</xsl:stylesheet>

On the other hand, if the element names are know beforehand and do not change, you can use them in the stylesheet:

Stylesheet ("static" element names)

<?xml version="1.0" encoding="utf-8"?>

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

   <xsl:output method="xml" indent="yes"/>
   <xsl:strip-space elements="*"/>

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

   <xsl:template match="aaa|bbb">
      <xsl:choose>
          <xsl:when test="text()">
              <xsl:copy-of select="."/>
          </xsl:when>
          <xsl:otherwise/>
      </xsl:choose>
   </xsl:template>

</xsl:stylesheet>

Output

<?xml version="1.0" encoding="UTF-8"?>
<a>
   <b>
      <aaa>val</aaa>
   </b>
</a>

You can create a empty template for the elements you want to omit, and an identity transform template for the other elements:

<xsl:template match="aaa[string-length(text()) = 0]" />
<xsl:template match="bbb[string-length(text()) = 0]" />

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

Need Your Help

# of servers for secure/best-practice setup of SQL Server 2005, Reporting Services, IIS

sql-server reportingservices-2005

I want to set up a SQL Server 2005 database, a Reporting Services instance, and IIS to view reports via the web and web applications.

"Add to favorite" function

uitableview plist nsuserdefaults

I need to have such functionality in my app as "add to favorite". I have UITableView with cells, where cell refer to DetailViewController that contains UIImageView. So I need to make such option, w...