Home > Mobile >  XSLT: Returning a value with a [not(object)] template match cuts template matches
XSLT: Returning a value with a [not(object)] template match cuts template matches

Time:03-08

I'm creating an XSLT where I want to get values from XML elements. If they do not exist, I want to ensure some default value is inserted. I tried making this work with XSL:template match, which works great, and then return a value if the element does not exist with xsl:template match="a/b/[not(c)]

This adds the default value, but then removes all other values.

I tried using xsl:apply-templates on top of this, to add all the existing objects' values too. This works, but only for a single [not(object)] clause. I.e., if there are multiple non-existing objects that are matched, only the last one is displayed along with all the matched objects.

How can I ensure I get all "default" values (or: values for non-existing objects) while also obtaining all the existing elements?

Here's a simplified version of my current XSLT:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:template match="/">
      <items>
          <xsl:apply-templates select="LinkedHashMap"/>
      </items>
  </xsl:template>
  
  <xsl:template match="A/items/itemA">
    <first>
      <xsl:value-of select="."/>
    </first>
  </xsl:template>
  
  <xsl:template match="A/items[not(itemA)]">
        <first>
            "Default value"
        </first>
        <xsl:apply-templates/>
    </xsl:template>
    
    
  <xsl:template match="A/items/itemB">
    <second>
      <xsl:value-of select="."/>
    </second>
  </xsl:template>
  <xsl:template match="A/items[not(itemB)]">
    <second>
        "Default value"
    </second>
    <xsl:apply-templates/>
  </xsl:template>
    
    
  <xsl:template match="A/items/itemC">
      <third>
        <xsl:value-of select="."/>
      </third>
  </xsl:template>
  <xsl:template match="A/items[not(itemC)]">
    <third>
        "Default value"
    </third>
    <xsl:apply-templates/>
  </xsl:template>
    
  <xsl:template match="A/items/itemD">
    <third>
      <xsl:value-of select="."/>
    </third>
    </xsl:template>
    <xsl:template match="A/items[not(itemD)]">
      <fourth>
        "Default value"
      </fourth>
    <xsl:apply-templates/>
  </xsl:template>
    
</xsl:stylesheet>

Input:

<LinkedHashMap>
    <A>
        <items>
            <itemA>First item</itemA>
            <itemB>Second item</itemB>
        </items>
    </A>
</LinkedHashMap>

Results in :

<?xml version="1.0" encoding="UTF-8"?>
<items>
    
        <fourth>
        "Default value"
      </fourth>
            <first>First item</first>
            <second>Second item</second>
        
    
</items>

Where I also expect to find a

<third>"default value"</third>

How can I ensure all default values are added here? Thanks!

CodePudding user response:

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

<xsl:template match="items">
  <xsl:copy>
    <xsl:choose>
      <xsl:when test="itemA">
        <xsl:apply-templates select="itemA"/>
      </xsl:when>
      <xsl:otherwise>
        <first>
          "Default value"
        </first>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test="itemB">
        <xsl:apply-templates select="itemB"/>
      </xsl:when>
      <xsl:otherwise>
        <second>
          "Default value"
        </second>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test="itemC">
        <xsl:apply-templates select="itemC"/>
      </xsl:when>
      <xsl:otherwise>
        <third>
          "Default value"
        </third>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test="itemD">
        <xsl:apply-templates select="itemD"/>
      </xsl:when>
      <xsl:otherwise>
        <forth>
          "Default value"
        </forth>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:copy>
</xsl:template>

<xsl:template match="itemA">
  <first>
    <xsl:value-of select="."/>
  </first>
</xsl:template>

<xsl:template match="itemB">
  <second>
    <xsl:value-of select="."/>
  </second>
</xsl:template>

<xsl:template match="itemC">
    <third>
      <xsl:value-of select="."/>
    </third>
</xsl:template>

<xsl:template match="itemD">
  <third>
    <xsl:value-of select="."/>
  </third>
</xsl:template>
  • Related