Jump to content

[solved] How To Compare Two Differents Attributes


subuntug

Recommended Posts

Hello; I have a little xml file, which is :

	<?xml version="1.0" ?>	<db>		  <cities>				 <city cityName="aaa" stateNumber="1"/>				  <city cityName="bbb" stateNumber="2"/>		 </cities>				 <states>				<state stateName="ccc" stateNumber="1"/>				<state sateName="ddd" stateNumber="3"/>		 </states>    </db>

I want to compare between an attribute of <city> and an attribute of <state>For this, I tried this code:

	   <xsl:for-each select="/db">			 <xsl:if test="/db/cities/city@stateNumber=/db/states/state@stateNumber">							 <tr>										   <td>   <xsl:value-of select="cities/city@cityName" /> </td>											<td>   xsl:value-of select="cities/city@stateNumber" /> </td>										   <td> <xsl:value-of select="states/state@stateNumber" /> </td>							</tr>			 </xsl:if>	 </xsl:for-each>

But, unfortunatelly, my xsl code doesn't work at all. The browser display an error message in my xsl file. for example in firefox, I got this kind of messages: Error loading stylesheet: XPath parse failure: binary operator expected:Thank you in advance

Link to comment
Share on other sites

Proper XPath syntax is e.g./db/cities/city/@stateNumber=/db/states/state/@stateNumberso all your path expressions lack a slash '/' before '@'.That should fix any syntax errors.As it is not clear what you want to achieve it is hard to fix any semantical errors in your stylesheet. If the stylesheet, after fixing the syntax errors, does not do what you want, consider to post the output you want for the sample input you have shown.

Link to comment
Share on other sites

Thank you for your answer martin. What I want to do is : get all the "cities" where stateName, stateNumber are avaible in my database. In the mysql world, "cities" and "states" are two different tables in one database. I already did an sql query which worked well: Its statement is:

SELECT cities.cityName, cities.stateNumber, states.stateName FROM cities, states WHERE cities.stateName=states.stateName;

In my example I expect to get:

  • aaa (which is the name of the city)
  • 1 (which is the number of the state where the city is located)
  • ccc (which is the name of the state where the city is located)

So, when I put / before @, the error disappeared, but I got nothing, my output is void. How can I do this query well ?Thank you for your help

Link to comment
Share on other sites

Your SQL does a "join" on stateName but as your posted XML sample does not have such an attribute on city and state I use the stateNumber attribute instead for the "join".Here are is one possible solution:

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">    <xsl:output method="html" indent="yes"/>    <xsl:template match="/">	<html>	  <head>		<title>Example</title>	  </head>	  <body>		<table>		  <thead>			<tr>			  <th>city name</th>			  <th>state number</th>			  <th>state name</th>			</tr>		  </thead>		  <tbody>			 <!-- select those city elements for which there is a state element with the same stateNumber attribute value -->			<xsl:for-each select="db/cities/city[@stateNumber = /db/states/state/@stateNumber]">			  <tr>				<td><xsl:value-of select="@cityName"/></td>				<td><xsl:value-of select="@stateNumber"/></td>				<td><xsl:value-of select="/db/states/state[@stateNumber = current()/@stateNumber]/@stateName"/></td>			  </tr>			</xsl:for-each>		  </tbody>		</table>	  </body>	</html>  </xsl:template></xsl:stylesheet>

And below is a second solution that makes use of keys and should that way be more efficient:

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">    <xsl:output method="html" indent="yes"/>    <xsl:key name="k1" match="state" use="@stateNumber"/>    <xsl:template match="/">	<html>	  <head>		<title>Example</title>	  </head>	  <body>		<table>		  <thead>			<tr>			  <th>city name</th>			  <th>state number</th>			  <th>state name</th>			</tr>		  </thead>		  <tbody>			<xsl:for-each select="db/cities/city[key('k1', @stateNumber)]">			  <tr>				<td><xsl:value-of select="@cityName"/></td>				<td><xsl:value-of select="@stateNumber"/></td>				<td><xsl:value-of select="key('k1', @stateNumber)/@stateName"/></td>			  </tr>			</xsl:for-each>		  </tbody>		</table>	  </body>	</html>  </xsl:template></xsl:stylesheet>

Link to comment
Share on other sites

Thank you very much four your help. Your code works for me ! all right. You're really a good xml programmer.But now I have a little problem with the same example. In fact, this time I need to extract the states number, where there is no city in my database belonging to that state.I tried this xsl code

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">	<xsl:output method="html"/>		<xsl:template match="/">	<html>	         <head>			<title>Example 2</title>					</head>		<body>				<table>										<thead>							<tr>							<th>stateNumber</th>													</tr>				</thead>				<tbody>						<xsl:for-each select="db/states/state[@stateNumber != /db/cities/city/@stateNumber]">						    								<tr>									<td><xsl:value-of select="@stateNumber"/></td>								</tr>														</xsl:for-each>				</tbody>										</table>				</body>	</html>	</xsl:template></xsl:stylesheet>

But, unfortunately, I didn't get what I expected, which means the numbers of the states which don't have cities in the database. instead I got a list of all states numbers existing in <state> element.I hope somebody would help me this time too.Thank you in advance.

Link to comment
Share on other sites

  • 1 year later...

I really like the second code as well. It's very clean and useful. A local company (www.coop-systems.com) creates such coding. Sub, is a problem with not having your cities defined by the states? In other words, are all the cities getting lined up with states? I'm trying to follow this logically without getting too much into coding, but frankly a lot of these people can blow me out of the water.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...