I appreciate that we ideally need to provide a working sample, but I think it might be tricky to do. But, I'll try.
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>
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>
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>
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, '-', '') > 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:
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.
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, '-', '') > 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.
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: