Click to See Complete Forum and Search --> : How to transform based on element content?
eslaydon
10-17-2007, 07:51 AM
I'm hoping that someone can help me figure out how to test the content of an XML element. I know how to do it if it is an attribute of the element but how do I get at the actual content?
For example I have the following snippet of xml:
<classContent>
<class>English</class>
<number>two</number>
</classContent>
I have the XSL outputing the class of English but I want to know how to get the XSL to do a transform on "two". In other words I want the XSL to do a test that says - if the element "number" content is equal to "two" then output "2". I have multiple values of the element "number" that I would want it to go through and replace. Is this possible with XML and XSL??
thanks
jkmyoung
10-18-2007, 10:55 AM
Yes this is, but you would need to have a listing of all possible values in your xsl. eg:
<my:mapping xmlns:my="internal">
<number text="zero" value="0"/>
<number text="one" value="1"/>
<number text="two" value="2"/>
<number text="three" value="3"/>
<number text="four" value="4"/>
<number text="five" value="5"/>
<number text="six" value="6"/>
<number text="seven" value="7"/>
<number text="eight" value="8"/>
<number text="nine" value="9"/>
</my:mapping>
When you get to the number node:
<xsl:template match="number">
<xsl:copy>
<xsl:value-of select="document('')//number[@text = current()]/@value"/>
</xsl:copy>
</xsl:template>
Mustermeister
10-28-2007, 02:21 PM
You could use if-statements like the following:
<xsl:if test="number='two'">2</xsl:if>
or you can use a choose statement:
<xsl.choose>
<xsl:when test="number='one'">1</xsl:when>
<xsl:when test="number='two'">2</xsl:when>
</xsl:choose>
or you can use multiple templates like this:
<xsl:template match="number[string()='two']">2</xsl:template>
or you can follow the advice above and create a mapping element, but it should be put in its own xml document like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<mapping>
<number text="zero" value="0"/>
<number text="one" value="1"/>
<number text="two" value="2"/>
<number text="three" value="3"/>
<number text="four" value="4"/>
<number text="five" value="5"/>
<number text="six" value="6"/>
<number text="seven" value="7"/>
<number text="eight" value="8"/>
<number text="nine" value="9"/>
</mapping>
If the file name is mapping.xml we compute the mapping like this:
<xsl:template match="number">
<xsl:value-of select="document('mapping.xml')/mapping/number[@text = current()]/@value"/>
</xsl:template>
Opera doesn't support the document() function however.
Mustermeister
10-28-2007, 06:02 PM
In XPath 2.0, hence in XSLT 2.0 sequence functions will become available. Then we can solve the problem like this:
<xsl:template match="number">
<xsl:value-of select="index-of(('one','two','three'),.)"/>
</xsl:template>
In the meantime there is a string solution:
<xsl:variable name="mapping">one1one,two2two,three3three</xsl:variable>
<xsl:template match="number">
<xsl:value-of select="substring-before(substring-after($mapping,.),.)"/>
</xsl:template>