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" ></bb>
<bb date="07.01.2023" num="prs2" ></bb>
</aa>
Here's the other
'2.xml'
<cc>
<dd id="prs1">
<ee>steak</ee>
<ff>
<gg >carrot cake</gg>
<gg >chocolate cake</gg>
<gg >cream cake</gg>
</ff>
</dd>
<dd id="prs2">
<ee>chicken</ee>
<ff>
<gg >Swiss roll</gg>
<gg >Napoleon cake</gg>
<gg >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>
CodePudding user response:
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.
CodePudding user response:
It looks like you want to
- convert every
bb
fromdoc1.xml
into atr
, - put its
date
attribute into atd
, - take the
bb
element'snum
attribute and look indoc2.xml
for add
with a matchingid
, and create a secondtd
with the value of theee
child of thedd
- then use the
bb
element'sclass
attribute to find anff/gg
descendant of thedd
with a matchingclass
attribute, and use its content to create a thirdtd
.
<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>