0

I have an XML doc with two sets of data in it. I need to output a HTML table that combines the data.

The XML looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<fdata>
    <RepairHistory>
        <RepairList>
            <RepairJob>
                <RepairRef>56740408</RepairRef>
                <RepairDescription>Baths</RepairDescription>
                <RepairReportedDate>20180515</RepairReportedDate>
                <RepairCompletedDate></RepairCompletedDate>
                <RepairStartDate>20180515</RepairStartDate>
            </RepairJob>
            <RepairJob>
                <RepairRef>56735043</RepairRef>
                <RepairDescription>Basins</RepairDescription>
                <RepairReportedDate>20180515</RepairReportedDate>
                <RepairCompletedDate></RepairCompletedDate>
                <RepairStartDate>20180515</RepairStartDate>
            </RepairJob>
            <RepairJob>
                <RepairRef>56740415</RepairRef>
                <RepairDescription>Showers</RepairDescription>
                <RepairReportedDate>20180515</RepairReportedDate>
                <RepairCompletedDate></RepairCompletedDate>
                <RepairStartDate>20180515</RepairStartDate>
            </RepairJob>
        </RepairList>
    </RepairHistory>
    <map>
        <entry>
            <string>GUID</string>
            <string>be0f53f5-7a09-47cd-9928-0c865b6450a5</string>
        </entry>
        <entry>
            <string>JOBNUMBER</string>
            <string>56740408</string>
        </entry>
    </map>
    <map>
        <entry>
            <string>GUID</string>
            <string>5ce2e8fe-7735-4f98-b3a9-3bd386edb338</string>
        </entry>
        <entry>
            <string>JOBNUMBER</string>
            <string>56740415</string>
        </entry>
    </map>
</fdata>

JOBNUMBER has to match RepairRef. Not all of the data at the bottom matches the data at the top. I need to output the data in a table as follows:

Date       Ref        Details    GUID
20180515   56740408   Baths      be0f53f5-7a09-47cd-9928-0c865b6450a5
20180515   56735043   Basins     No GUID
20180515   56740415   Showers    5ce2e8fe-7735-4f98-b3a9-3bd386edb338

I have tried to output the table using the following xsl, but it doesn't work...

<xsl:template match="/">
    <h3>Repair history</h3>
    <table>
        <tr>
            <th>Date</th>
            <th>Ref</th>
            <th>Details</th>
            <th>GUID</th>
        </tr>               
        <xsl:apply-templates select ="//RepairJob" />
    </table>
</xsl:template>
<xsl:template match="RepairJob">
    <xsl:variable name="JobNumber" select="RepairRef" />
     <tr>
         <td><xsl:value-of select="RepairStartDate"/></td>
         <td><xsl:value-of select="RepairRef"/></td>
         <td><xsl:value-of select="RepairDescription"/></td>
         <td>
            <xsl:choose>
                <xsl:when test="count(//map//entry[2]//string[2] = $JobNumber) &gt; 0">
                     <xsl:value-of select="//map//entry[2]//string[2] = $JobNumber"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>No GUID</xsl:text>
                </xsl:otherwise>
            </xsl:choose>                
        </td>
     </tr>
</xsl:template>

I can see that I am not selecting the correct node to display, but the matching is not working either. Can anyone help?

1 Answer 1

1

Your current xsl:value-of evaluates to a boolean ("true" or "false"). The expression you actually want is this...

<xsl:value-of select="//map[entry[2]/string[2] = $JobNumber]/entry[1]/string[2]"/>

The xsl:when needs a tweak too, so the whole xsl:choose should look like this:

<xsl:choose>
    <xsl:when test="//map[entry[2]/string[2] = $JobNumber]">
         <xsl:value-of select="//map[entry[2]/string[2] = $JobNumber]/entry[1]/string[2]"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:text>No GUID</xsl:text>
    </xsl:otherwise>
</xsl:choose>    

However, consider using a key to look up the guids....

<xsl:key name="map" match="map" use="entry[string[1] = 'JOBNUMBER']/string[2]" />

Then your xsl:value-of becomes this

<xsl:value-of select="key('map',$JobNumber)/entry[string[1] = 'GUID']/string[2]"/>

Note, this also allows for the entry elements to be in any order within a map element (i.e. the JOBNUMBER could be the first entry, and the GUID the second)

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html" indent="yes" />

<xsl:key name="map" match="map" use="entry[string[1] = 'JOBNUMBER']/string[2]" />

<xsl:template match="/">
    <h3>Repair history</h3>
    <table>
        <tr>
            <th>Date</th>
            <th>Ref</th>
            <th>Details</th>
            <th>GUID</th>
        </tr>               
        <xsl:apply-templates select ="//RepairJob" />
    </table>
</xsl:template>

<xsl:template match="RepairJob">
    <xsl:variable name="JobNumber" select="RepairRef" />
     <tr>
         <td><xsl:value-of select="RepairStartDate"/></td>
         <td><xsl:value-of select="RepairRef"/></td>
         <td><xsl:value-of select="RepairDescription"/></td>
         <td>
            <xsl:choose>
                <xsl:when test="key('map',$JobNumber)">
                     <xsl:value-of select="key('map',$JobNumber)/entry[string[1] = 'GUID']/string[2]"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>No GUID</xsl:text>
                </xsl:otherwise>
            </xsl:choose>                
        </td>
     </tr>
</xsl:template>
</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

1 Comment

In XSLT 2.0 the xsl:choose simplifies to <xsl:value-of select="(key('map',$JobNumber)/entry[string[1] = 'GUID']/string[2], 'No GUID')[1]"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.