Reputation: 5
I have two xml files, named 1.xml and 2.xml. '1.xml' consists of two elements, aa and bb. 'bb' has three attributes: date, num and class.
'2.xml' has five elements, cc, dd> ee, ff and gg. Two of them got one attribute each: 'dd' (id) and 'ff' (class).
I want to make a xsl that uses the values of the date attribute from '1.xml' to find the id element in '2xml' with the corresponding attribute values.
'1.xml':
<aa>
<bb date="31.12.2022" num="prs1" class="alt_3"></bb>
<bb date="07.01.2023" num="prs2" class="alt_2"></bb>
</aa>
Here's the other
'2.xml'
<cc>
<dd id="prs1">
<ee>steak</ee>
<ff>
<gg class="alt_1">carrot cake</gg>
<gg class="alt_2">chocolate cake</gg>
<gg class="alt_3">cream cake</gg>
</ff>
</dd>
<dd id="prs2">
<ee>chicken</ee>
<ff>
<gg class="alt_1">Swiss roll</gg>
<gg class="alt_2">Napoleon cake</gg>
<gg class="alt_3">marzipan cake</gg>
</ff>
</dd>
</cc>
This is what I want to get:
<table>
<tr>
<td>31.12.2022</td>
<td>steak</td>
<td>cream cake</td>
</tr>
<tr>
<td>07.01.2023</td>
<td>chicken</td>
<td>Napoleon cake</td>
</tr>
</table>
This is what I've got so far:
<body>
<table>
<tr>
<td>31.12.2022</td>
<td></td>
</tr>
<tr>
<td>07.01.2023</td>
<td></td>
</tr>
</table>
<xsl:template match="aa">
<html>
<body>
<table>
<xsl:for-each select="bb">
<tr>
<td><xsl:value-of select="@date"/></td>
<td><xsl:variable name="bbnum" select="@num"/>
<xsl:variable name="bbid" select="document('2.xml')/cc[@id = current()/dd/@id]/*"/>
<xsl:if test="$bbnum!=$bbid">
<xsl:value-of select="ee"/>
</xsl:if> </td>
<td></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
Upvotes: 0
Views: 57
Reputation: 3258
It looks like you want to
bb
from doc1.xml
into a tr
,date
attribute into a td
,bb
element's num
attribute and look in doc2.xml
for a dd
with a matching id
, and create a second td
with the value of the ee
child of the dd
bb
element's class
attribute to find an ff/gg
descendant of the dd
with a matching class
attribute, and use its content to create a third td
.<xsl:template match="aa">
<xsl:variable name="doc2" select="document('2.xml')"/>
<html>
<body>
<table>
<xsl:for-each select="bb">
<xsl:variable name="bb-num" select="@num"/>
<xsl:variable name="dd" select="$doc2/cc/dd[@id=$bb-num]"/>
<xsl:variable name="bb-class" select="@class"/>
<xsl:variable name="gg" select="$dd/ff/gg[@class=$bb-class]"/>
<tr>
<td><xsl:value-of select="@date"/></td>
<td><xsl:value-of select="$dd/ee"/></td>
<td><xsl:value-of select="$gg"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
Upvotes: 0
Reputation: 117100
If your processor supports XSLT 2.0 or higher, then you could do:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="k1" match="dd" use="@id" />
<xsl:key name="k2" match="gg" use="@class" />
<xsl:template match="/aa">
<html>
<body>
<table>
<xsl:for-each select="bb">
<xsl:variable name="dd" select="key('k1', @num, document('2.xml'))" />
<tr>
<td>
<xsl:value-of select="@date"/>
</td>
<td>
<xsl:value-of select="$dd/ee"/>
</td>
<td>
<xsl:value-of select="key('k2', @class, $dd)"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
If you are limited to XSLT 1.0, then it's a little more complicated, but still doable.
Upvotes: 1