XSLT: how to check if all certain nodes in one parent

I am trying to recall an XSL snippet that will check to see if a class has all students with the same name. Yes, then (do something like) type "all last names are the same" else print "all last names are not the same."

No matter what to print. I'm just trying to find the right logic for him.

Here is my XML example:

<root> <class name="Physics"> <student> <firstname>John</firstname> <lastname>Doe</lastname> <age>21</age> </student> <student> <firstname>Mary</firstname> <lastname>Doe</lastname> <age>21</age> </student> <student> <firstname>Ralph</firstname> <lastname>Doe</lastname> <age>21</age> </student> </class> <class name="Math"> <student> <firstname>John</firstname> <lastname>Doe</lastname> <age>21</age> </student> <student> <firstname>Mary</firstname> <lastname>Doe</lastname> <age>21</age> </student> <student> <firstname>Tee</firstname> <lastname>Rex</lastname> <age>21</age> </student> </class> </root> 

Therefore, for the physics class, he will print "all last names are the same." And for the math class, he will print "all the last names are not the same."

(This is not my real XML, because it was irreducible to a smaller problem, so instead I made this XML to represent my problem)

Any help would be greatly appreciated.

Regards, Shobhit

+4
source share
3 answers

Hm. Without knowing anything about your problem, I would do the following:

 <xsl:template match="class"> <xsl:choose> <xsl:when test=" count(student[not(lastname = preceding-sibling::student/lastname)]) = 1 "> <xsl:text>all lastnames are same</xsl:text> <xsl:when> <xsl:otherwise> <xsl:text>all lastnames are not same</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> 

XPath expression

 student[not(lastname = preceding-sibling::student/lastname)] 

selects all <student> nodes whose <lastname> not like any previous name in the same class.

In classes with all the same last names, their number is 1 (because the very first student always has the last name, unlike any previous last name). If the counter is greater than 1, then some students in this class have different last names.

The case when the class has no students at all will be recognized in the case of <xsl:otherwise> in the above logic. You might want to handle this case explicitly in some way.

+4
source

This style sheet:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="student"/> <xsl:template match="student[1]">all lastnames are same</xsl:template> <xsl:template match="student[1][lastname != ../student/lastname]" priority="1">all lastnames are not same</xsl:template> </xsl:stylesheet> 

Result:

 <root> <class name="Physics">all lastnames are same</class> <class name="Math">all lastnames are not same</class> </root> 

Note: Comparison of Nodeset.

Edit : Sorry miss @name.

Change 2 . Compact. Pay attention to @priority to avoid error recovery.

+2
source

This conversion is:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my" > <xsl:output method="text"/> <xsl:key name="kstudentByName" match="student" use="lastname"/> <my:text> <text> not </text> </my:text> <xsl:variable name="vText" select="document('')/*/my:text/*"/> <xsl:template match="/"> <xsl:variable name="vNumNames" select= "count(*/*/student[generate-id() = generate-id(key('kstudentByName', lastname)[1]) ] ) > 1 "/> All names are <xsl:value-of select="$vText[$vNumNames]"/> the same. </xsl:template> </xsl:stylesheet> 

when applied to the provided XML document, it gives the correct result:

  All names are not the same. 

Pay attention to the use of keys, which makes this conversion much more effective than the time-squared complexity of comparing each name with the names of all previous siblings

+1
source

Source: https://habr.com/ru/post/1314863/


All Articles