Storing text values in Variable of previous nodes
Input
<?xml version="1.0" encoding="UTF-8"?>
<XML>
<Concept>
<Heading-1>This is First Heading</Heading-1>
</Concept>
<Concept>
<Heading-2>This is Second Heading</Heading-2>
</Concept>
<Concept>
<Heading-2>This is First Heading</Heading-2>
</Concept>
</XML>
Output should be
<?xml version="1.0" encoding="UTF-8"?>
<name>This_is_First_Heading</name>
<name>This_is_Second_Heading</name>
<name>1_This_is_First_Heading</name>
Stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet开发者_开发百科 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="2.0">
<xsl:template match="Concept">
<xsl:variable name="name"
select="./Heading-1/text() | ./Heading-2/text()"/>
<xsl:variable name="name1"
select="if //Cocept/Heading-1/text()=$name
then concat(position(), '_' $name)}
else $name"/>
<name>
<xsl:value-of select="replace($name, ' ', '_' )"/>
</name>
</xsl:template>
</xsl:stylesheet>
Problem: I need to print all the heading text values under "name" element. But if there is similar text value present for previous hading it should add position() number before the text values. I need to do it though variable only, if you can see in Variable name1 i am trying to put some logic which will compare the value of previous heading and if come across the similar text then put the position number, but somehow am not able to achieve that. Can you please help me write same logic in variable name1. Thanks in advance for your help.
______Edited_________
<xsl:template match="Concept">
<xsl:variable name="name"
select="if (./Heading-1[1] |
./Heading-2[1] |
./Heading-3[1] |
./Heading-4[1] |
./Heading-5[1])
then normalize-space((Heading-1[1] |
Heading-2[1] |
Heading-3[1] |
Heading-4[1] |
Heading-5[1])
/text()[position()=last()])
else normalize-space(./Heading-2[1]/text()[2])"/>
<xsl:variable name="name1"
select="if (//Concept/Heading-3/text()
[position()=last()] = $name)
then concat(position(), '_', $name)
else $name"></xsl:variable>
<xsl:variable name="name2"
select="if (string-length($name5)=0)
then concat(position(), '_', $name5)
else $name5"/>
<xsl:result-document href="XML/{replace($name2, ' ', '_')}.xml"
format="testing" validation="strip">
One of the simplest possible XSLT 2.0 solutions:
<xsl:stylesheet version="2.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="/*/*/*">
<name>
<xsl:sequence select=
"concat(for $cnt in count(../preceding-sibling::*/*[. eq current()])
return
if($cnt gt 0)
then concat($cnt, '_')
else (),
.
)
"/>
</name>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<XML>
<Concept>
<Heading-1>This is First Heading</Heading-1>
</Concept>
<Concept>
<Heading-2>This is Second Heading</Heading-2>
</Concept>
<Concept>
<Heading-2>This is First Heading</Heading-2>
</Concept>
</XML>
produces the wanted, correct result:
<name>This is First Heading</name>
<name>This is Second Heading</name>
<name>1_This is First Heading</name>
In case you need each of the text nodes produced in the result to be actually in variables, then simply replace in the above code <xsl:sequence>
with <xsl:variable>
.
Here is a sample stylesheet that produces the result you asked for:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="k1" match="Concept/*" use="."/>
<xsl:template match="Concept/*">
<xsl:variable name="preceding" select="key('k1', .)[. << current()]"/>
<name>
<xsl:choose>
<xsl:when test="$preceding">
<xsl:value-of select="concat(count($preceding), '_', replace(., ' ', '_'))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="replace(., ' ', '_')"/>
</xsl:otherwise>
</xsl:choose>
</name>
</xsl:template>
</xsl:stylesheet>
精彩评论