Count nodes ignoring empty nodes

I have the following XML.

Case 1

<body> <nd> <pnn>1.1</pnn> <h1>PART 54</h1> <ti>Construction</ti> </nd> <nd> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Time</ti> </nd> <nd> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Power</ti> </nd> <nd> <h1>PART 54</h1> <h2>II APPLICATIONS</h2> <ti>Filing</ti> </nd> </body> 

Case 2

 <body> <nd> <pnn>1.1</pnn> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Construction</ti> </nd> <nd> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Time</ti> </nd> <nd> <h1>PART 54</h1> <h2>II APPLICATIONS</h2> <ti>Filing</ti> </nd> </body> 

and below XSLT

 <?xml version="1.0" encoding="UTF-8" ?> <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> <xsl:template match="/"> <hmtl> <head> <title>New Version!</title> </head> <xsl:apply-templates select="body"></xsl:apply-templates> </hmtl> </xsl:template> <xsl:template match="body"> <xsl:for-each select="nd"> <xsl:apply-templates select = "."/> </xsl:for-each> </xsl:template> <xsl:template match="pnn"/> <xsl:template match="h1"/> <xsl:template match="h2"/> <xsl:template match="ti"/> <xsl:variable name="FinalChap"> <xsl:value-of select="substring-before((//pnn)[1],'.')"/> </xsl:variable> <xsl:variable name="FinalChn"> <xsl:value-of select="$FinalChap"/> </xsl:variable> <xsl:variable name="Finalchapternumber"> <xsl:value-of select="format-number($FinalChn,'00')"/> </xsl:variable> <xsl:template name="section" match="nd"> <xsl:variable name="count"> <xsl:number count="nd" level="any"/> </xsl:variable> <xsl:variable name="classname"> <!--Get name attribute of current node --> <xsl:value-of select="concat('section-sect','1')"/> </xsl:variable> <xsl:variable name="classname1"> <!--Get name attribute of current node --> <xsl:value-of select="concat('section-sect','2')"/> </xsl:variable> <xsl:variable name="classname2"> <!--Get name attribute of current node --> <xsl:value-of select="concat('section-sect','3')"/> </xsl:variable> <!--Create a string variable by concat string method --> <xsl:variable name="sectionname"> <xsl:value-of select="concat('CH_',$Finalchapternumber,'-SEC-', $count)"/> </xsl:variable> <div class="{$classname}"> <xsl:if test="./h2 and not(preceding::h2[1]/text() = ./h2/text())"> <a name="{$sectionname}"> </a> <div class="section-title"> <xsl:if test="not(preceding::h2[1]/text() = ./h2/text())"> <xsl:apply-templates select="h2" mode="section"/> </xsl:if> </div> </xsl:if> <xsl:if test="not(lower-case(./ti/text()) = lower-case(./h2/text()))"> <xsl:if test="./ti"> <div class="{$classname2}"> <xsl:apply-templates select="ti" mode="section"/> </div> </xsl:if> </xsl:if> <xsl:apply-templates select="child::node()[not(self::h2|self::ti)]"/> </div> </xsl:template> <xsl:template match="ti" mode="section"> <xsl:apply-templates select="./node()[1][self::page]" mode="first"/> <xsl:variable name="sectionnum"> <xsl:number count="nd" level="any"/> </xsl:variable> <a name="CH_{$Finalchapternumber}-SEC-{$sectionnum}"/> <div class="section-title"> <xsl:apply-templates/> </div> </xsl:template> <xsl:template match="h2" mode="section"> <div class="section-title"> <xsl:apply-templates select="child::node()[not(self::fnt)]"/> </div> </xsl:template> </xsl:transform> 

here I am trying to increase the section number based on the condition. The count should be done if there is no node (here h2 ) <a name="CH_01-SEC-XX"></a> should be ignored, I can do this with <xsl:if test="./h2 and not(preceding::h2[1]/text() = ./h2/text())"> but the problem I am facing is count is not ignoring it.

Current exit. Case 1

 <div class="section-sect1"> <a name="CH_01-SEC-1"/> <div class="section-title"> <div class="section-title">I INTRODUCT</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-1"/> <div class="section-title">Construction</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-2"/> <div class="section-title">Time</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-3"/> <div class="section-title">Power</div> </div> </div> <div class="section-sect1"> <a name="CH_01-SEC-4"/> <div class="section-title"> <div class="section-title">II APPLICATIONS</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-4"/> <div class="section-title">Filing</div> </div> </div> 

Expected Output Case 1

 <div class="section-sect1"> <a name="CH_01-SEC-1"/> <div class="section-title"> <div class="section-title">I INTRODUCT</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-2"/> <div class="section-title">Construction</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-3"/> <div class="section-title">Time</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-4"/> <div class="section-title">Power</div> </div> </div> <div class="section-sect1"> <a name="CH_01-SEC-5"/> <div class="section-title"> <div class="section-title">II APPLICATIONS</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-6"/> <div class="section-title">Filing</div> </div> </div> 

Current output 2

 <div class="section-sect1"><a name="CH_01-SEC-1"></a><div class="section-title"> <div class="section-title">I INTRODUCT</div> </div> <div class="section-sect3"><a name="CH_01-SEC-1"></a><div class="section-title">Construction</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"><a name="CH_01-SEC-2"></a><div class="section-title">Time</div> </div> </div> <div class="section-sect1"><a name="CH_01-SEC-3"></a><div class="section-title"> <div class="section-title">II APPLICATIONS</div> </div> <div class="section-sect3"><a name="CH_01-SEC-3"></a><div class="section-title">Filing</div> </div> </div> 

Expected Result Case 2

 <div class="section-sect1"> <a name="CH_01-SEC-1"/> <div class="section-title"> <div class="section-title">I INTRODUCT</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-2"/> <div class="section-title">Construction</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-3"/> <div class="section-title">Time</div> </div> </div> <div class="section-sect1"> <a name="CH_01-SEC-4"/> <div class="section-title"> <div class="section-title">II APPLICATIONS</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-5"/> <div class="section-title">Filing</div> </div> </div> 

there is a duplicate in the current output CH_01-SEC-1 Can someone please let me know how to make it in series 1...n

Here is a working DEmo

thanks

+6
source share
1 answer

What about....

 <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0"> <xsl:output method="html" doctype-public="XSLT-compat" encoding="UTF-8" indent="yes" /> <xsl:strip-space elements="*" /> <xsl:variable name="FinalChap"> <xsl:value-of select="format-number( xs:integer( substring-before((/body/nd/pnn)[1],'.')), '00')"/> </xsl:variable> <xsl:template match="/"> <html> <head><title>New Version from Sean!</title></head> <xsl:apply-templates /> </html> </xsl:template> <xsl:template match="*"> <xsl:apply-templates /> </xsl:template> <xsl:template match="text()|processing-instruction()|comment()|@*" /> <xsl:template match="body"> <xsl:for-each-group select="nd" group-adjacent="h2/text()"> <xsl:variable name="group-position" select="position()" /> <xsl:for-each select="current-group()"> <xsl:call-template name="nd"> <xsl:with-param name="group-position" select="$group-position" /> <xsl:with-param name="is-head" select="position() eq 1" as="xs:boolean" /> </xsl:call-template> </xsl:for-each> </xsl:for-each-group> </xsl:template> <xsl:template name="nd"> <xsl:param name="group-position" select="1" as="xs:integer" /> <xsl:param name="is-head" select="true()" as="xs:boolean" /> <div class="section-sect1"> <xsl:if test="$is-head"> <xsl:call-template name="a-link"> <xsl:with-param name="group-position" select="$group-position" /> <xsl:with-param name="delta" select="0" as="xs:integer" /> </xsl:call-template> <div class="section-title"> <div class="section-title"><xsl:value-of select="h2" /></div> </div> </xsl:if> <div class="section-sect3"> <xsl:call-template name="a-link"> <xsl:with-param name="group-position" select="$group-position" /> <xsl:with-param name="delta" select="1" as="xs:integer" /> </xsl:call-template> <div class="section-title"><xsl:value-of select="ti" /></div> </div> </div> </xsl:template> <xsl:template name="a-link"> <xsl:param name="group-position" select="1" as="xs:integer" /> <xsl:param name="delta" select="0" as="xs:integer" /> <a name="CH_{$FinalChap}-SEC-{$group-position + count(preceding-sibling::nd) + $delta}" /> </xsl:template> </xsl:transform> 

The above conversion applies to the input document ...

 <body> <nd> <pnn>1.1</pnn> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Construction</ti> </nd> <nd> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Time</ti> </nd> <nd> <h1>PART 54</h1> <h2>I INTRODUCT</h2> <ti>Power</ti> </nd> <nd> <h1>PART 54</h1> <h2>II APPLICATIONS</h2> <ti>Filing</ti> </nd> </body> 

... prints output ...

 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>New Version from Sean!</title> </head> <div class="section-sect1"> <a name="CH_01-SEC-1"/> <div class="section-title"> <div class="section-title">I INTRODUCT</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-2"/> <div class="section-title">Construction</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-3"/> <div class="section-title">Time</div> </div> </div> <div class="section-sect1"> <div class="section-sect3"> <a name="CH_01-SEC-4"/> <div class="section-title">Power</div> </div> </div> <div class="section-sect1"> <a name="CH_01-SEC-5"/> <div class="section-title"> <div class="section-title">II APPLICATIONS</div> </div> <div class="section-sect3"> <a name="CH_01-SEC-6"/> <div class="section-title">Filing</div> </div> </div> </html> 

Description

The body template uses the xsl: for-each-group to group nd elements into common adjacent h2 (h2 headers). The xsl: for-each-group sequence constructor calls the nd pattern to process each nd element in order, passing it the group number and whether that nd first ("head") of the nd group.

I deduced from your example that the head nd each group creates additional content related to the group, including the additional link a.

The a-link number (for example, 4 in CH_01-SEC-4 ) is equal to the account of the previous nd, plus the group number plus the additional 1, if we are not a chapter.

Alternative solutions

Just as there are many ways to throw a cat, there are several alternative solutions that would be equally valid. Instead of grouping, you can use the full push design. Additional content for the head nodes ( <div class="section-title"> ) can be achieved using the template template predicate by comparing this h2 with the previous h2. And the correcting number of a-links can be achieved by micro-pipelining.

+1
source

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


All Articles