问题
I've been trying to learn how to code in xslt and currently am stuck on how to use conditional tests around the xsl:apply-templates tag.
Here's the xml that I am testing.
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
Here is my xslt
<xsl:template match="/">
<xsl:apply-templates select="catalog/cd" />
</xsl:template>
<xsl:template match="cd">
<p>
<xsl:apply-templates select="artist" />
<br />
<xsl:apply-templates select="country" />
<br />
<xsl:if test="country != 'USA' and year != '1985'">
<xsl:apply-templates select="year" />
</xsl:if>
</p>
</xsl:template>
<xsl:template match="artist">
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="country">
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="year">
<xsl:value-of select="." />
</xsl:template>
Here is my output:
Bob Dylan
USA
Bonnie Tyler
UK
1988
Dolly Parton
USA
Here is the output I was expecting:
Bob Dylan
USA
Bonnie Tyler
UK
1988
Dolly Parton
USA
1982
Even though I want to remove the year only when country has a value of USA and year has a value of 1985 it is removing the year every time country has a value of USA only. Is there a better way I can use apply-templates?
回答1:
You might prefer to apply templates to the wanted node set directly, without conditional "if" check.
<xsl:apply-templates select="year[not(../country='USA' and ../year='1985)]" />
回答2:
Simply correct your logic.
Replace:
<xsl:if test="country != 'USA' and year != '1985'">
with:
<xsl:if test="country != 'USA' or year != '1985'">
and even better, apply templates only on the wanted nodes:
<xsl:apply-templates select=
"self::*[country != 'USA' or year != '1985']/year"/>
Do note:
As demonstrated, it is possible to specify the Xpath expression in the select
attribute without using any reverse axes (going back and forth).
回答3:
This helped me, thank you.
I was expanding upon this very example and trying to call one template for a certain attribute (I had edited the XML to eg <artist sex="male">Bob Dylan</artist>
My attempts were failing but i worked it out. This code allowed me to create conditional templates in >1 scenario: -
<xsl:template match="cd">
<p>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="artist [@sex = 'male']"/>
<xsl:apply-templates select="artist [@sex = 'female']"/>
<xsl:apply-templates select="year"/>
</p>
</xsl:template>
<xsl:template match="title">
Title: <span style="color:#ff0000">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
<xsl:template match="artist [@sex = 'male']">
Artist: <span style="color:#e9d419">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
<xsl:template match="artist [@sex = 'female']">
Artist: <span style="color:#48b8ff">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
<xsl:template match="year">
Year: <span style="color:#eb47dc">
<xsl:value-of select="."/></span>
<br />
</xsl:template>
Hope this helps and is useful to someone! The output produced the artist name in a different colour depending on their sex.
回答4:
You want to remove the year if the country is USA and if the year is 1985.
Therefore, you want to copy the year if the country is not USA or if the year is not 1985.
Your condition should use an or
instead of an and
. Note that not(a and b) = (not a) or (not b)
.
来源:https://stackoverflow.com/questions/11023458/conditional-test-around-xslapply-templates