2

I have the following xml:

<?xml version="1.0" encoding="UTF-8"?>
<abc1 formName="Form">
    <Level1>
        <Element1>ZZZ</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Pears</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Milkshakes</SubElement5>
        </Element2>
    </Level1>
    <Level1>
        <Element1>XXX</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Kiwifruit</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Soda</SubElement5>
        </Element2>
    </Level1>
</abc1>

and what I need to be able to do is take a look at the values in some nodes, determine if they are different, and if so write some different html code with a page break between each section.

So, I need to compare the <Element1> values and see if they are different. The <Element1> values could be any text, and the number of <Element1>tags could be unlimited in the xml.

So in this case, we have two different <Element1> values: 'ZZZ' and 'XXX'.

So something like the following if there are two '':

<xsl:choose>
<xsl:when test="differentvalues = 'true'">
<!--  SomeHTMLCode!-->
<p style="page-break-after: always"/>
<!--  SomeHTMLCode!-->
</xsl:when>
<xsl:otherwise><!--  SomeHTMLCode!--></xsl:otherwise>
</xsl:choose>

but using the for-loop to search through the xml, and something like

<xsl:choose>
<xsl:when test="differentvalues = 'true'">
<!--  SomeHTMLCode!-->
<p style="page-break-after: always"/>
<!--  SomeHTMLCode!-->
<p style="page-break-after: always"/>
<!--  SomeHTMLCode!-->
</xsl:when>
<xsl:otherwise><!--  SomeHTMLCode!--></xsl:otherwise>
</xsl:choose>

if there are three different </Element1> values.

I'm not even sure if this can be done. Thanks in advance for any help you can provide me with.

2
  • Isn't this the same question again? Commented Jun 7, 2012 at 13:23
  • I suppose it is similar, but I have not been working with xslt that long and thought of them as a little different. Commented Jun 7, 2012 at 14:57

1 Answer 1

1

This XPath expression gives you the wanted count of distinct values for Element1 (supposing an Element1 cannot have a descendent also Element1 (there is more efficient way to handle such problems using keys, but I wouldn't talk about keys to a newbie):

count(//Element1[not(. = preceding::Element1)])

You can define a variable specifying the above value in its select attribute and then use this variable in the test attribute` of your conditional instructions.

Even better, don't use conditional instructions at all and specify the above XPath expression as part of a template match pattern:

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

 <xsl:template match="/*[count(//Element1[not(. = preceding::Element1)]) = 2]">
     Two processing
 </xsl:template>

 <xsl:template match="/*[count(//Element1[not(. = preceding::Element1)]) = 3]">
     Three processing
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<abc1 formName="Form">
    <Level1>
        <Element1>ZZZ</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Pears</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Milkshakes</SubElement5>
        </Element2>
    </Level1>
    <Level1>
        <Element1>XXX</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Kiwifruit</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Soda</SubElement5>
        </Element2>
    </Level1>
</abc1>

the wanted, correct result is produced:

 Two processing

When the same transformation is applied on the following XML document:

<abc1 formName="Form">
    <Level1>
        <Element1>ZZZ</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Pears</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Milkshakes</SubElement5>
        </Element2>
    </Level1>
    <Level1>
        <Element1>YYY</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Pears</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Milkshakes</SubElement5>
        </Element2>
    </Level1>
    <Level1>
        <Element1>XXX</Element1>
        <Element2>
            <SubElement1>Apples</SubElement1>
            <SubElement2>Oranges</SubElement2>
            <SubElement3>Kiwifruit</SubElement3>
            <SubElement4>Blueberries</SubElement4>
            <SubElement5>Soda</SubElement5>
        </Element2>
    </Level1>
</abc1>

again the correct result is produced:

 Three processing

Note:

You need, of course, to substitute the bodies of the templates with your desired processing.

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

4 Comments

Thanks. This is fantastic. I've never seen that before. What if the number of 'Levels' is unknown? Is there anything you could do then? You setup the code for two, and three....but what if its unknown?
@CooperCripps: This solution works with any number of Level -s and with any nesting of Level -s. Could you, please, accept this answer (by clicking the check-mark next to it?
Hi Dimitre, but you listed two templates: one for 'Two Processing' and one for 'Three Processing'. Lets say I didn't know if there was 'Five Processing or 'Ten Processing'. I don't understand how it would then work with any number of levels if you only have two templates. Sorry if this is a bit of a layman question.
@CooperCripps: I was guided only by the text of your question. In case the possible count is statically unknown, then you will have in a single template an <xsl:choose> with many `<xsl:when> s for every interval of values for the count that you want to process in a specific way.

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.