Search code examples
javascriptxslt-1.0webview2

Unable to either pass LabelsInfo.xml into second transform or reference it directly in second transform


I appreciate that we ideally need to provide a working sample, but I think it might be tricky to do. But, I'll try.

Labels Info

I have a labels XML file:

<?xml version="1.0" encoding="UTF-8"?>
<Labels Version="24100002">
    <Platform>Platform</Platform>
    <Mike Index="1">Mike Left</Mike>
    <Mike Index="2">Mike Right</Mike>
    <Attendant Index="1">Car Park Attendant</Attendant>
    <Attendant Index="2">Entrance Attendant</Attendant>
    <Attendant Index="3">Auditorium Attendant</Attendant>
</Labels>

Duty History

I have a duty history file. Example:

<?xml version="1.0" encoding="utf-8"?>
<DutyAssignmentHistory xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.publictalksoftware.co.uk/msa">
  <DutyAssignments>
    <DutyAssignmentEntry Date="2018-12-30" Week="W20181224" Template="0" Mode="Weekend">
      <Assignment Index="1" IndexType="Fixed">4</Assignment>
      <Assignment Index="7" IndexType="Fixed">3</Assignment>
      <Assignment Index="14" IndexType="Fixed">2</Assignment>
      <Assignment Index="5" IndexType="Custom">1</Assignment>
    </DutyAssignmentEntry>
    <DutyAssignmentEntry Date="2019-01-03" Week="W20181231" Template="0" Mode="Midweek">
      <Assignment Index="1" IndexType="Fixed">Damien Gailes</Assignment>
      <Assignment Index="5" IndexType="Fixed">Felix Thompson</Assignment>
    </DutyAssignmentEntry>
    <DutyAssignmentEntry Date="2019-01-06" Week="W20181231" Template="0" Mode="Weekend">
      <Assignment Index="1" IndexType="Fixed">1</Assignment>
      <Assignment Index="13" IndexType="Fixed">4</Assignment>
      <Assignment Index="14" IndexType="Fixed">3</Assignment>
    </DutyAssignmentEntry>
    <DutyAssignmentEntry Date="2019-01-10" Week="W20190107" Template="0" Mode="Midweek">
      <Assignment Index="1" IndexType="Fixed">2</Assignment>
      <Assignment Index="8" IndexType="Fixed">1</Assignment>
    </DutyAssignmentEntry>
  </DutyAssignments>
</DutyAssignmentHistory>

Main XSL

This is the main XSL file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msa="http://www.publictalksoftware.co.uk/msa">

    <xsl:variable name="DutyDB" select="document('DutyAssignHistory.xml')"/>
    <xsl:variable name="PubDB" select="document('MSA_PublisherDatabase.xml')"/>
    <xsl:variable name="LabelsInfo" select="document('LabelsInfo.xml')"/>

    <xsl:output method="html" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <html>
            <head>
                <title>Duty History Test</title>
                <link rel="stylesheet" type="text/css" href="Custom--S-140--ComboNames2.css"/>
                <script type="text/javascript">
                    function showAlert() {
                    var select = document.getElementById('publisherCombo');
                    var selectedText = select.options[select.selectedIndex].text;
                    // alert("Selected Publisher: " + selectedText);
                    }

                    function saveDate() {
                    var selectedDate = document.getElementById('datePicker').value;
                    // alert("Selected Date: " + selectedDate);
                    // Save the date to a variable for further use
                    window.selectedDate = selectedDate;
                    }

                    function filterHistory() {
                    var selectedName = document.getElementById('publisherCombo').value;
                    var selectedDate = document.getElementById('datePicker').value.replace(/-/g, '');

                    // Filter and display the results using the selected name and date
                    var xsl = loadXMLDoc('Custom--S-140--ComboNames2-transform.xsl');
                    var xml = loadXMLDoc('DutyAssignHistory.xml');
                    // var labelsInfo = loadXMLDoc('LabelsInfo.XML');

                    var xsltProcessor = new XSLTProcessor();
                    xsltProcessor.importStylesheet(xsl);
                    xsltProcessor.setParameter(null, 'selectedName', selectedName);
                    xsltProcessor.setParameter(null, 'selectedDate', selectedDate);

                    // Set LabelsInfo as a parameter
                    // xsltProcessor.setParameter(null, 'LabelsInfo', new XMLSerializer().serializeToString(labelsInfo));

                    var resultDocument = xsltProcessor.transformToFragment(xml, document);
                    document.getElementById('output').innerHTML = '';
                    document.getElementById('output').appendChild(resultDocument);
                    }

                    function loadXMLDoc(filename) {
                    var xhttp = new XMLHttpRequest();
                    xhttp.open('GET', filename, false);
                    xhttp.send();
                    return xhttp.responseXML;
                    }
                </script>
            </head>
            <body>
                <h2 class="no-print">Select a Publisher:</h2>
                <select id="publisherCombo" onchange="showAlert()" class="no-print">
                    <xsl:for-each select="$PubDB/msa:PublisherDatabase/msa:Publishers/msa:Publisher[@Gender='Male']">
                        <xsl:sort select="msa:Name" order="ascending" data-type="text"/>
                        <option>
                            <xsl:value-of select="msa:Name"/>
                        </option>
                    </xsl:for-each>
                </select>

                <h2 class="no-print">Select a Date:</h2>
                <input type="date" id="datePicker" onchange="saveDate()" class="no-print"/>

                <button onclick="filterHistory()" class="no-print">Filter</button>

                <div id="output"></div>

                <div>
                    <h3>Index Legend</h3>
                    <ul>
                        <li>
                            <xsl:text>5: </xsl:text>
                            <xsl:value-of select="$LabelsInfo/Labels/Platform"/>
                        </li>
                        <li>
                            <xsl:text>7: </xsl:text>
                            <xsl:value-of select="$LabelsInfo/Labels/Mike[@Index='1']"/>
                        </li>
                        <li>
                            <xsl:text>8: </xsl:text>
                            <xsl:value-of select="$LabelsInfo/Labels/Mike[@Index='2']"/>
                        </li>
                        <li>
                            <xsl:text>13: </xsl:text>
                            <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='1']"/>
                        </li>
                        <li>
                            <xsl:text>14: </xsl:text>
                            <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='2']"/>
                        </li>
                        <li>
                            <xsl:text>15: </xsl:text>
                            <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='3']"/>
                        </li>
                    </ul>
                </div>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

Transform XSL

It refers to this transform XSL file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msa="http://www.publictalksoftware.co.uk/msa">

    <xsl:param name="selectedDate" select="''"/>
    <xsl:param name="selectedName" select="''"/>
    
    <xsl:output method="html" encoding="UTF-8" indent="yes"/>

    <!-- Template to match the root and start the transformation -->
    <xsl:template match="/">
        <html>
            <head>
                <title>Filtered Duty Assignment History</title>
                <style>
                    table {
                    border-collapse: collapse;
                    }

                    table, th, td {
                    border: 1px solid black;
                    }

                    th, td {
                    padding: 8px;
                    text-align: left;
                    }

                    th {
                    background-color: #f2f2f2;
                    }

                    tr:hover {
                    background-color: #e0e0e0;
                    }
                </style>
            </head>
            <body>
                <h2>Filtered Duty Assignment History</h2>
                <table>
                    <tr>
                        <th>
                            <xsl:text>Date</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Mode</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Index</xsl:text>
                        </th>
                        <th>
                            <xsl:text>IndexType</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Name</xsl:text>
                        </th>
                    </tr>
                    <xsl:apply-templates select="//msa:DutyAssignmentEntry/msa:Assignment[text() = $selectedName and translate(../@Date, '-', '') &gt; translate($selectedDate, '-', '')]"/>
                </table>
            </body>
        </html>
    </xsl:template>

    <!-- Template to display each filtered duty assignment -->
    <xsl:template match="msa:Assignment">
        <tr>
            <td>
                <xsl:value-of select="../@Date"/>
            </td>
            <td>
                <xsl:value-of select="../@Mode"/>
            </td>
            <td>
                <xsl:value-of select="@Index"/>
            </td>
            <td>
                <xsl:value-of select="@IndexType"/>
            </td>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>
    </xsl:template>

</xsl:stylesheet>

Result:

enter image description here

It works. My problem is that I actually wanted to use the LabelsInfo.xml content inside the second transform xsl script. But if I simply include the labels file into the second script and use $LabelsInfo it is empty. I also tried passing it as a parameter in filterHistory function because it still did not work.

Ideally I don't want a legend. I would prefer a Duty column in my table with the description instead of the index. But I fail every time.

I am running my XSL transform in WebView2 browser.


I can supply some more recent duty history if required. And I redacted real names in the screenshot.


Update

If I change filterHistory():

function filterHistory() {

    var selectedName = document.getElementById('publisherCombo').value;
    var selectedDate = document.getElementById('datePicker').value.replace(/-/g, '');
    
    // Filter and display the results using the selected name and date
    var xsl = loadXMLDoc('Custom--S-140--ComboNames2-transform.xsl');
    var xml = loadXMLDoc('DutyAssignHistory.xml');
    var labelsInfo = loadXMLDoc('LabelsInfo.XML');
    
    var xsltProcessor = new XSLTProcessor();
    xsltProcessor.importStylesheet(xsl);
    xsltProcessor.setParameter(null, 'selectedName', selectedName);
    xsltProcessor.setParameter(null, 'selectedDate', selectedDate);
    
    // Set LabelsInfo as a parameter
    xsltProcessor.setParameter(null, 'LabelsInfo', new XMLSerializer().serializeToString(labelsInfo));
    
    var resultDocument = xsltProcessor.transformToFragment(xml, document);
    document.getElementById('output').innerHTML = '';
    document.getElementById('output').appendChild(resultDocument);
}

And then add it as a parameter into the transform XSL file with extra code:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msa="http://www.publictalksoftware.co.uk/msa">

    <xsl:param name="selectedDate" select="''"/>
    <xsl:param name="selectedName" select="''"/>
    <xsl:param name="LabelsInfo" select="''"/>

    <xsl:output method="html" encoding="UTF-8" indent="yes"/>

    <!-- Template to match the root and start the transformation -->
    <xsl:template match="/">
        <html>
            <head>
                <title>Filtered Duty Assignment History</title>
                <style>
                    table {
                    border-collapse: collapse;
                    }

                    table, th, td {
                    border: 1px solid black;
                    }

                    th, td {
                    padding: 8px;
                    text-align: left;
                    }

                    th {
                    background-color: #f2f2f2;
                    }

                    tr:hover {
                    background-color: #e0e0e0;
                    }
                </style>
            </head>
            <body>
                <xsl:copy-of select="$LabelsInfo"/>
                <h2>Filtered Duty Assignment History</h2>
                <table>
                    <tr>
                        <th>
                            <xsl:text>Date</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Mode</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Duty</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Index</xsl:text>
                        </th>
                        <th>
                            <xsl:text>IndexType</xsl:text>
                        </th>
                        <th>
                            <xsl:text>Name</xsl:text>
                        </th>
                    </tr>
                    <xsl:apply-templates select="//msa:DutyAssignmentEntry/msa:Assignment[text() = $selectedName and translate(../@Date, '-', '') &gt; translate($selectedDate, '-', '')]"/>
                </table>
            </body>
        </html>
    </xsl:template>

    <!-- Template to display each filtered duty assignment -->
    <xsl:template match="msa:Assignment">
        <tr>
            <td>
                <xsl:value-of select="../@Date"/>
            </td>
            <td>
                <xsl:value-of select="../@Mode"/>
            </td>
            <td>
                <xsl:copy-of select="$LabelsInfo"/>
                <!--<xsl:choose>
                    <xsl:when test="@Index='5'">
                        <xsl:value-of select="$LabelsInfo/Labels/Platform"/>
                    </xsl:when>
                    <xsl:when test="@Index='7'">
                        <xsl:value-of select="$LabelsInfo/Labels/Mike[@Index='1']"/>
                    </xsl:when>
                    <xsl:when test="@Index='8'">
                        <xsl:value-of select="$LabelsInfo/Labels/Mike[@Index='2']"/>
                    </xsl:when>
                    <xsl:when test="@Index='13'">
                        <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='1']"/>
                    </xsl:when>
                    <xsl:when test="@Index='14'">
                        <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='2']"/>
                    </xsl:when>
                    <xsl:when test="@Index='15'">
                        <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='3']"/>
                    </xsl:when>
                </xsl:choose>-->
            </td>
            <td>
                <xsl:value-of select="@Index"/>
            </td>
            <td>
                <xsl:value-of select="@IndexType"/>
            </td>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>
    </xsl:template>

</xsl:stylesheet>

This works, I can see the full XML data $LabelsInfo. But the moment I uncomment this bit:

                <!--<xsl:choose>
                    <xsl:when test="@Index='5'">
                        <xsl:value-of select="$LabelsInfo/Labels/Platform"/>
                    </xsl:when>
                    <xsl:when test="@Index='7'">
                        <xsl:value-of select="$LabelsInfo/Labels/Mike[@Index='1']"/>
                    </xsl:when>
                    <xsl:when test="@Index='8'">
                        <xsl:value-of select="$LabelsInfo/Labels/Mike[@Index='2']"/>
                    </xsl:when>
                    <xsl:when test="@Index='13'">
                        <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='1']"/>
                    </xsl:when>
                    <xsl:when test="@Index='14'">
                        <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='2']"/>
                    </xsl:when>
                    <xsl:when test="@Index='15'">
                        <xsl:value-of select="$LabelsInfo/Labels/Attendant[@Index='3']"/>
                    </xsl:when>
                </xsl:choose>-->

It stops working. At first I thought it might be confused by the use of @Index in both elements, but even <xsl:value-of select="$LabelsInfo/Labels/Platform"/> will cause it to fail.


I think the reason it fails is because he variable is a string and not a lookupable xml data variable.


Solution

  • I came up with a working solution. I modifid filterHistory():

    function filterHistory() {
    
        var selectedName = document.getElementById('publisherCombo').value;
        var selectedDate = document.getElementById('datePicker').value.replace(/-/g, '');
        
        // Filter and display the results using the selected name and date
        var xsl = loadXMLDoc('ComboNames2-transform.xsl');
        var xml = loadXMLDoc('DutyAssignHistory.xml');
        var labelsInfo = loadXMLDoc('LabelsInfo.XML');
        
        var xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xsl);
        xsltProcessor.setParameter(null, 'selectedName', selectedName);
        xsltProcessor.setParameter(null, 'selectedDate', selectedDate);
        xsltProcessor.setParameter(null, 'index5', labelsInfo.documentElement.getElementsByTagName('Platform')[0].textContent.trim());
        xsltProcessor.setParameter(null, 'index7', labelsInfo.documentElement.getElementsByTagName('Mike')[0].textContent.trim());
        xsltProcessor.setParameter(null, 'index8', labelsInfo.documentElement.getElementsByTagName('Mike')[1].textContent.trim());
        xsltProcessor.setParameter(null, 'index13', labelsInfo.documentElement.getElementsByTagName('Attendant')[0].textContent.trim());
        xsltProcessor.setParameter(null, 'index14', labelsInfo.documentElement.getElementsByTagName('Attendant')[1].textContent.trim());
        xsltProcessor.setParameter(null, 'index15', labelsInfo.documentElement.getElementsByTagName('Attendant')[2].textContent.trim());
        
        var resultDocument = xsltProcessor.transformToFragment(xml, document);
        document.getElementById('output').innerHTML = '';
        document.getElementById('output').appendChild(resultDocument);
    
    }
    

    I load the labels file and pass the required labels as parameters. So in my secondary XSL file I now have:

    <xsl:param name="index5" select="''"/>
    <xsl:param name="index7" select="''"/>
    <xsl:param name="index8" select="''"/>
    <xsl:param name="index13" select="''"/>
    <xsl:param name="index14" select="''"/>
    <xsl:param name="index15" select="''"/>
    

    Which means I can call:

    
    <!-- Template to display each filtered duty assignment -->
    <xsl:template match="msa:Assignment">
        <tr>
            <td>
                <xsl:value-of select="../@Date"/>
            </td>
            <td>
                <xsl:value-of select="../@Mode"/>
            </td>
            <td>
                <xsl:choose>
                    <xsl:when test="@Index='5'">
                        <xsl:value-of select="$index5"/>
                    </xsl:when>
                    <xsl:when test="@Index='7'">
                        <xsl:value-of select="$index7"/>
                    </xsl:when>
                    <xsl:when test="@Index='8'">
                        <xsl:value-of select="$index8"/>
                    </xsl:when>
                    <xsl:when test="@Index='13'">
                        <xsl:value-of select="$index13"/>
                    </xsl:when>
                    <xsl:when test="@Index='14'">
                        <xsl:value-of select="$index14"/>
                    </xsl:when>
                    <xsl:when test="@Index='15'">
                        <xsl:value-of select="$index15"/>
                    </xsl:when>
                </xsl:choose>
            </td>
            <td>
                <xsl:value-of select="@Index"/>
            </td>
            <td>
                <xsl:value-of select="@IndexType"/>
            </td>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>
    </xsl:template>
    
    

    It works fine:

    enter image description here