|
Subject:
|
How to resolve IDREF in XSL
|
|
Posted By:
|
teahouse
|
Post Date:
|
9/15/2006 11:55:52 AM
|
Hi,
I am a newbie to XML/XSLT. I searched on this forum, however did not find exactly what I look up. Basically, I have two tables A and B, A contains a REF (a foreign key to B), so when I display table A using XSL, since I have the idref to B's entry, how can I extract attribute from B?
For illustration purpose, I have a database DTD for tools and customers, and sample tool.xml, and its corresponding tool.xsl. How do I display the customer's name, instead of the current refID (I'm using borrower/@bid) (which is cust1)? See all the file below.
Thanks for help!
-Tao
================== tool.dtd =============== <!ELEMENT database (tools|customers)*>
<!ELEMENT tools (tool)* > <!ELEMENT tool (toolname, borrower*)>
<!ELEMENT toolname (#PCDATA)> <!ELEMENT borrower EMPTY> <!ATTLIST borrower bid IDREF #REQUIRED>
<!ELEMENT customers (customer)*> <!ELEMENT customer (name, address) > <!ATTLIST customer cid ID #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT address (#PCDATA)>
================== tool.xml===============
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE database SYSTEM "tool.dtd">
<?xml-stylesheet type="text/xsl" href="tool.xsl"?>
<database> <tools> <tool> <toolname>Foo Bar</toolname> <borrower bid="cust1" /> </tool> </tools> <customers> <customer cid="cust1"> <name>Ben Jackson</name> <address>688 Adams Alley, Cincinnati, OH</address> </customer> </customers>
</database> ================== tool.xsl =============== <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" omit-xml-declaration="no" doctype-system="http://www.w3c.org/TR/xhtml/DTD/xhtml1-strict.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"/>
<xsl:template match="/"> <!-- match root element --> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>This is a Tool Collection</title> </head>
<body> <h2>My Tool Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Tool Name</th> <th>Borrower ID</th> <th>Borrower Name</th> </tr>
<xsl:for-each select="database/tools/tool"> <tr> <td> <xsl:value-of select="toolname"/> </td> <td> <xsl:value-of select="borrower/@bid"/> </td> </tr> </xsl:for-each> </table>
</body> </html> </xsl:template> </xsl:stylesheet>
|
|
Reply By:
|
joefawcett
|
Reply Date:
|
9/15/2006 12:25:45 PM
|
There are at least three approaches, the first is to use something like:<xsl:for-each select="database/tools/tool">
<tr>
<td>
<xsl:value-of select="toolname"/>
</td>
<td>
<xsl:value-of select="borrower/@bid"/>
</td>
<td>
<xsl:value-of select="/*/customers/customer[@cid = current()/borrower/@bid]/name"/>
</td>
</tr>
</xsl:for-each>
The current() function refers to the context node before the XPath expression is evaluated, alternatively you could store the value in a variable.
The better way to do this is to declare a key to access the customers. <xsl:key name="customerById" match="customer" use="@cid"/>
This needs to be outside of any xsl:template element.
You can then use this to retrieve customers:<xsl:for-each select="database/tools/tool">
<tr>
<td>
<xsl:value-of select="toolname"/>
</td>
<td>
<xsl:value-of select="borrower/@bid"/>
</td>
<td>
<xsl:value-of select="key('customerById', borrower/@bid)/name"/>
</td>
</tr>
</xsl:for-each> Thirdly, as you have defined @cid to be of type ID then you can use the id function:<xsl:for-each select="database/tools/tool">
<tr>
<td>
<xsl:value-of select="toolname"/>
</td>
<td>
<xsl:value-of select="borrower/@bid"/>
</td>
<td>
<xsl:value-of select="id(borrower/@bid)/name"/>
</td>
</tr>
</xsl:for-each>
--
Joe (Microsoft MVP - XML)
|
|
Reply By:
|
mhkay
|
Reply Date:
|
9/15/2006 12:35:37 PM
|
You can use the id() function. If @ref is an IDREF attribute, then id(@ref) returns the element whose ID it contains.
This is rather dependent on ID's being notified to the XSLT processor. Sometimes this breaks down, for example if you add a preprocessing phase to your transformation pipeline. Some people therefore recommend using keys instead. Declare
<xsl:key name="customer-id" match="customer" use="id"/>
and then key('customer-id', @ref)
will give you the customer whose ID value is in @ref.
Michael Kay http://www.saxonica.com/ Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|
|
Reply By:
|
teahouse
|
Reply Date:
|
9/15/2006 1:14:42 PM
|
Joe/Michael,
Thank you so much for the prompt replies. I'll try them out.
Thanks again!!! -Tao
|