I am trying to create a generic XSLT that will work with multiple types of queries. I found an XSLT format that seems to work for everything I need, except looping to the next user. Within the program that I am using, a query is created and it puts out XML. That XML creates a table with the labels at the top and all the information following in the correct columns. This information includes Guest, Access Type, and Access Type Description. Except I don't want the Guest ID inside of the table, I want it on the top of the table with only Access Type and Access Description inside the table. And I want the XSLT to create a new table for each guest listed. That is where I am running into the problem. I tried to create a variable and I tried Muenchian grouping but I can't seem to get it figured out. I was also wondering if I set up the title incorrectly for the table? I can also only use Version 1.0 of XSLT.
XML
<query xmlns:xsi="; numrows="2" queryname="EXAMPLE_GUEST_VIEW" xsi:noNamespaceSchemaLocation="">
<row rownumber="1">
<GUEST_USERID>
<![CDATA[ ID#1 ]]>
</GUEST_USERID>
<GUEST_NAME>
<![CDATA[ ID#1 - User Name 1 ]]>
</GUEST_NAME>
<ACCESS_TYPE>
<![CDATA[ Access Type Name ]]>
</ACCESS_TYPE>
<ACCESS_DESCRIPTION>
<![CDATA[ Access Type Description. ]]>
</ACCESS_DESCRIPTION>
</row>
<row rownumber="2">
<GUEST_USERID>
<![CDATA[ ID#2 ]]>
</GUEST_USERID>
<GUEST_NAME>
<![CDATA[ ID#2 - User Name 2 ]]>
</GUEST_NAME>
<ACCESS_TYPE>
<![CDATA[ Access Type Name ]]>
</ACCESS_TYPE>
<ACCESS_DESCRIPTION>
<![CDATA[ Access Type Description. ]]>
</ACCESS_DESCRIPTION>
</row>
</query>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="; version="1.0">
<xsl:template match="/">
<div>
<xsl:apply-templates select="Scroll0"/>
</div>
</xsl:template>
<xsl:template match="Scroll0">
<xsl:choose>
<xsl:when test="count(Row) > 0">
<table class="{@class}">
<xsl:if test="@class != ''">
<span><strong><xsl:value-of select="Row[1]/Field2"/></strong></span>
</xsl:if>
<tr><xsl:apply-templates select="Row[1]/*[position() > 1]" mode="headers"/></tr>
<xsl:apply-templates select="Row"/>
</table>
</xsl:when>
<xsl:otherwise>
<div class="alert alert-info">No Guest Listed</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Row/*" mode="headers">
<th id="{local-name(.)}" class="{@class}">
<xsl:choose><xsl:when test="@label != ''"><xsl:value-of select="@label"/></xsl:when><xsl:otherwise><xsl:value-of select="local-name(.)"/></xsl:otherwise></xsl:choose>
</th>
</xsl:template>
<xsl:template match="Row">
<tr>
<xsl:apply-templates select="*[position() > 1]"/>
</tr>
</xsl:template>
<xsl:template match="Row/*">
<td headers="{local-name(.)}" class="{@class}">
<xsl:choose><xsl:when test=". != ''"><xsl:value-of select="."/></xsl:when><xsl:otherwise> </xsl:otherwise></xsl:choose>
</td>
</xsl:template>
</xsl:stylesheet>
Final XML Output
<?xml version="1.0"?>
<div>
<table class="table table-condensed table-hover">
<span><strong> ID#1 - User Name 1</strong></span>
<tr>
<th class="" id="Field3">Access Type</th>
<th class="" id="Field4">Description</th>
</tr>
<tr>
<td class="" headers="Field3"> Access Type Name </td>
<td class="" headers="Field4"> Access type description. </td>
</tr>
<tr>
<td class="" headers="Field3"> Access Type Name </td>
<td class="" headers="Field4"> Access type description. </td>
</tr>
</table>
</div>
I am trying to create a generic XSLT that will work with multiple types of queries. I found an XSLT format that seems to work for everything I need, except looping to the next user. Within the program that I am using, a query is created and it puts out XML. That XML creates a table with the labels at the top and all the information following in the correct columns. This information includes Guest, Access Type, and Access Type Description. Except I don't want the Guest ID inside of the table, I want it on the top of the table with only Access Type and Access Description inside the table. And I want the XSLT to create a new table for each guest listed. That is where I am running into the problem. I tried to create a variable and I tried Muenchian grouping but I can't seem to get it figured out. I was also wondering if I set up the title incorrectly for the table? I can also only use Version 1.0 of XSLT.
XML
<query xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" numrows="2" queryname="EXAMPLE_GUEST_VIEW" xsi:noNamespaceSchemaLocation="">
<row rownumber="1">
<GUEST_USERID>
<![CDATA[ ID#1 ]]>
</GUEST_USERID>
<GUEST_NAME>
<![CDATA[ ID#1 - User Name 1 ]]>
</GUEST_NAME>
<ACCESS_TYPE>
<![CDATA[ Access Type Name ]]>
</ACCESS_TYPE>
<ACCESS_DESCRIPTION>
<![CDATA[ Access Type Description. ]]>
</ACCESS_DESCRIPTION>
</row>
<row rownumber="2">
<GUEST_USERID>
<![CDATA[ ID#2 ]]>
</GUEST_USERID>
<GUEST_NAME>
<![CDATA[ ID#2 - User Name 2 ]]>
</GUEST_NAME>
<ACCESS_TYPE>
<![CDATA[ Access Type Name ]]>
</ACCESS_TYPE>
<ACCESS_DESCRIPTION>
<![CDATA[ Access Type Description. ]]>
</ACCESS_DESCRIPTION>
</row>
</query>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<div>
<xsl:apply-templates select="Scroll0"/>
</div>
</xsl:template>
<xsl:template match="Scroll0">
<xsl:choose>
<xsl:when test="count(Row) > 0">
<table class="{@class}">
<xsl:if test="@class != ''">
<span><strong><xsl:value-of select="Row[1]/Field2"/></strong></span>
</xsl:if>
<tr><xsl:apply-templates select="Row[1]/*[position() > 1]" mode="headers"/></tr>
<xsl:apply-templates select="Row"/>
</table>
</xsl:when>
<xsl:otherwise>
<div class="alert alert-info">No Guest Listed</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Row/*" mode="headers">
<th id="{local-name(.)}" class="{@class}">
<xsl:choose><xsl:when test="@label != ''"><xsl:value-of select="@label"/></xsl:when><xsl:otherwise><xsl:value-of select="local-name(.)"/></xsl:otherwise></xsl:choose>
</th>
</xsl:template>
<xsl:template match="Row">
<tr>
<xsl:apply-templates select="*[position() > 1]"/>
</tr>
</xsl:template>
<xsl:template match="Row/*">
<td headers="{local-name(.)}" class="{@class}">
<xsl:choose><xsl:when test=". != ''"><xsl:value-of select="."/></xsl:when><xsl:otherwise> </xsl:otherwise></xsl:choose>
</td>
</xsl:template>
</xsl:stylesheet>
Final XML Output
<?xml version="1.0"?>
<div>
<table class="table table-condensed table-hover">
<span><strong> ID#1 - User Name 1</strong></span>
<tr>
<th class="" id="Field3">Access Type</th>
<th class="" id="Field4">Description</th>
</tr>
<tr>
<td class="" headers="Field3"> Access Type Name </td>
<td class="" headers="Field4"> Access type description. </td>
</tr>
<tr>
<td class="" headers="Field3"> Access Type Name </td>
<td class="" headers="Field4"> Access type description. </td>
</tr>
</table>
</div>
My python code:
from lxml import etree
xml_ = "tem.xml"
xsl_ = "tem.xsl"
xsl_p = etree.parse(xsl_)
transform = etree.XSLT(xsl_p)
xml_p = etree.parse(xml_)
result = transform(xml_p)
# Write the transformed XML to a file
output_file = 'transformed_output.html '
with open(output_file, 'wb') as file:
file.write(etree.tostring(result, pretty_print=True, encoding='UTF-8'))
print(f"Transformed HTML written to {output_file}")
You can try this tem.xsl (XSLT) to get an html:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Tabelle</title>
<style>
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
}
th {
background-color: #f2f2f2;
text-align: left;
}
span strong {
display: block;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div>
<xsl:for-each select="query/row">
<table class="table table-condensed table-hover">
<span>
<strong>
<xsl:value-of select="GUEST_NAME"/>
</strong>
</span>
<tr>
<th class="" id="Field3">Access Type</th>
<th class="" id="Field4">Description</th>
</tr>
<tr>
<td class="" headers="Field3">
<xsl:value-of select="ACCESS_TYPE"/>
</td>
<td class="" headers="Field4">
<xsl:value-of select="ACCESS_DESCRIPTION"/>
</td>
</tr>
</table>
</xsl:for-each>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Output in Browser:
<xsl:apply-templates select="Scroll0"/>
(there is noScroll0
element in the input) and ending with your expected (?) output showing only one user out of the two in the input. In any case, CDATA is just data like any other data. – michael.hor257k Commented Jan 2 at 21:23span
element as a child of atable
element? Why would you need (Muenchian) grouping if the sample data you show has two distinctrow
s with distinctGUEST_USERID
s? – Martin Honnen Commented Jan 2 at 22:49