XSL: How do I use "and" operator to compare a position and if node exist

How do I use "and" operator to compare a position and if node exist

For example I have following input
<Compl>
      <person Type="ONE">
            <Name>
                  <Fname>SMITH</Fname>
                  <Lname>JOHN</Lname>
            </Name>
            <misc Type="TWO>
                  <Fname>SMITH</Fname>
                  <Lname>JAkE</Lname>
            </misc>
      </person>
</Compl>

And I want output to be ONE/TWO

I have following code
<xsl:for-each select="Compl/person">
      <xsl:value-of select="./@Type"/>
      <xsl:if test="position() != last() and misc">
            <xsl:value-of select="'/'"/>
      </xsl:if>
</xsl:for-each>
badtz7229Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Geert BormansConnect With a Mentor Information ArchitectCommented:
Yep, I just tested the code and given that all the person nodes are wrapped in a Compl node as the document root, this XSLT gives you what you need

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="/">
        <xsl:for-each select="Compl/person/@Type | Compl/person/misc/@Type">
            <xsl:if test="not(position() = 1)">
                <xsl:text>/</xsl:text>
            </xsl:if>
            <xsl:value-of select="."/>
        </xsl:for-each>          
    </xsl:template>
</xsl:stylesheet>

Open in new window


with this XML that would be

<?xml version="1.0" encoding="UTF-8"?>
<Compl>
    <person Type="CCC">
        <Name>
            <Fname>TEMP</Fname>
            <Lname>ANYTHING</Lname>
        </Name>
    </person>
    <person Type="AAA">
        <Name>
            <Fname>TEMP</Fname>
            <Lname>ANYTHING</Lname>
        </Name>
        <misc Type="III">
            <Fname>TEMP</Fname>
            <Lname>ANYTHING</Lname>
        </misc>
    </person>
    <person Type="AAA">
        <Name>
            <Fname>TEMP</Fname>
            <Lname>ANYTHING</Lname>
        </Name>
    </person> 
</Compl>

Open in new window

0
 
zc2Commented:
Yes, you can check a node existence just by mentioning its name in the test string.

Here's an example with the following improvements:
1) Use templates instead of for-each
2) Use <xsl:text> instead of <xsl:value-of select="'/'"/>
 I'm not sure, what's your goal besides printing out ONE/TWO, so I've removed that "position() != last()" test.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<xsl:apply-templates select="Compl/person"/>
	</xsl:template>
	
	<xsl:template match="person|misc">
		<xsl:value-of select="@Type"/>
	      <xsl:if test="misc">
	      	<xsl:text>/</xsl:text>
            <xsl:apply-templates select="misc"/>
	      </xsl:if>
 	</xsl:template>
</xsl:stylesheet>

Open in new window

0
 
Geert BormansInformation ArchitectCommented:
That is exacxtly how you need to use "and"

But I think you want more than that

you need a
<xsl:value-of select="misc/@Type"/>
too
for the "Two"
0
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

 
Geert BormansInformation ArchitectCommented:
Maybe you were thinking in terms of

<xsl:for-each select="Compl/person/@Type | Compl/person/misc/@Type">
      <xsl:if test="not(position() = 1)">
            <xsl:text>/</xsl:text>
      </xsl:if>
      <xsl:value-of select="."/>
</xsl:for-each> 

Open in new window


is making the Type attributes the selected node-set
0
 
badtz7229Author Commented:
i need the position() in case there are more <person> then i want to seperate the @type with "/"
0
 
badtz7229Author Commented:
in this example, i'd want CCC/AAA/III/AAA

            <person Type="CCC">
                  <Name>
                        <Fname>TEMP</Fname>
                        <Lname>ANYTHING</Lname>
                  </Name>
            </person>
            <person Type="AAA">
                  <Name>
                        <Fname>TEMP</Fname>
                        <Lname>ANYTHING</Lname>
                  </Name>
                  <misc Type="III">
                        <Fname>TEMP</Fname>
                        <Lname>ANYTHING</Lname>
                  </misc>
            </person>
            <person Type="AAA">
                  <Name>
                        <Fname>TEMP</Fname>
                        <Lname>ANYTHING</Lname>
                  </Name>
            </person>
0
 
Geert BormansInformation ArchitectCommented:
OK, but you have the "two" in the misc/@Type inside Person,
that is what caused my comment
So you will need a "/" between Types inside the same person and between persons,
hence my suggestion to collect the nodest of wanted @Type attributes
0
 
Geert BormansInformation ArchitectCommented:
OK, I did not see your example before posting.
But the approach with the @Type nodeset will give you that
0
 
badtz7229Author Commented:
thx. that worked.
0
 
Geert BormansInformation ArchitectCommented:
welcome
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.