htmlxmlxslt-1.0cdata

How do I use XSLT to create a loop with XML that includes CDATA?


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) &gt; 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() &gt; 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() &gt; 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>&#160;</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>

Solution

  • 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: enter image description here