0

I have an XML flow where I need to insert content based on the whether an element contains data or if it is empty.

I've tried several techniques but it's still not working.

Here is my XSLT:

<?xml version="1.0" encoding="UTF-8"?><!-- DWXMLSource="pricesample.xml" -->
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8"/>

<xsl:template match="catalog">

<catalog>
<xsl:for-each select="shoe">
<shoe>
<xsl:value-of select="name"/><xsl:text> </xsl:text>
<xsl:apply-templates select="price" />
</shoe>
</xsl:for-each>
</catalog>
</xsl:template>

<xsl:template match="price">
  <xsl:choose>
    <xsl:when test=". =''">
      <price><xsl:text>Price is Empty</xsl:text></price><xsl:text>
      </xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <price><xsl:text> $</xsl:text><xsl:value-of select="."/></price><xsl:text>
      </xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


</xsl:stylesheet>

Here is the XML:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<shoe>
    <name>Shoe 1</name>
    <price>49.98</price>
</shoe>
<shoe>
    <name>Shoe 2</name>
    <price>65.5</price>
</shoe>
<shoe>
    <name>Shoe 3</name>
    <price>70</price>
</shoe>
<shoe>
    <name>Shoe 4</name>
    <price/>
</shoe>
<shoe>
    <name>Shoe 5</name>
    <price/>
</shoe>
</catalog>

So the output should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<shoe>
    <name>Shoe 1</name>
    <price>$49.98</price>
</shoe>
<shoe>
    <name>Shoe 2</name>
    <price>$65.5</price>
</shoe>
<shoe>
    <name>Shoe 3</name>
    <price>$70</price>
</shoe>
<shoe>
    <name>Shoe 4</name>
    <price>Price is Empty</price>
</shoe>
<shoe>
    <name>Shoe 5</name>
    <price>Price is Empty</price>
</shoe>
</catalog>

I have tried several tests, including:

test=". =''"
test="not(price)"
test="not(string(.))"

None of them seem to work for me.

6
  • 1
    Before asking new questions, please take care of your last questions: this one and this one. If there is a valid answer, accept it. If the question became obsolete, delete the question. Commented Dec 19, 2014 at 19:55
  • 1
    Oh, and also this one, this one and this one - and this one. Commented Dec 19, 2014 at 19:58
  • 1
    And this one - sorry for these spam-like comments, but you should really tidy up a dozen older questions before moving on. Commented Dec 19, 2014 at 20:04
  • 1
    I see that you need close guidance on this. Accept your own answer to this question. Delete this question - it is simply not true that there is a problem with the XLST code you wrote there. For this question you promised to let the answerer "know if it works" - but did not do it. Commented Dec 19, 2014 at 20:51
  • 1
    You never really made it clear why the two answers to this question are not acceptable. For this question, a commenter made it clear that you did not clearly state the requirement and failed to show the expected output. For this question, there are several valuable answers, and you have not accepted any of them. Commented Dec 19, 2014 at 20:54

1 Answer 1

2

Please do heed Mathias' suggestion to take care of your old questions. You should select an accepted answer when there is one that works, not just move on to the next question.

The answer to your question is fairly simple with an identity template and template pattern matching.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>

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

  <xsl:template match="price">
    <xsl:copy>
      <xsl:value-of select="concat('$', .)" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="price[not(node())]">
    <xsl:copy>Price is Empty</xsl:copy>
  </xsl:template>

</xsl:stylesheet>

When run on your sample input, the result is:

<catalog>
  <shoe>
    <name>Shoe 1</name>
    <price>$49.98</price>
  </shoe>
  <shoe>
    <name>Shoe 2</name>
    <price>$65.5</price>
  </shoe>
  <shoe>
    <name>Shoe 3</name>
    <price>$70</price>
  </shoe>
  <shoe>
    <name>Shoe 4</name>
    <price>Price is Empty</price>
  </shoe>
  <shoe>
    <name>Shoe 5</name>
    <price>Price is Empty</price>
  </shoe>
</catalog>

XsltCake

Sign up to request clarification or add additional context in comments.

2 Comments

OK, but the original question also added a dollar sign to the output. Do I insert an <xsl:text>$</xsl:text> in front of <xsl:apply-templates select="@* | node()" />
@JimMaivald Sorry, I missed that (please make sure to clearly describe the behavior you want and not just show an example of it). I've updated my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.