html - How do I use XSLT to create a loop with XML that includes CDATA? - Stack Overflow

admin2025-05-01  1

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) &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>

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>
Share Improve this question asked Jan 2 at 21:11 MPourierMPourier 53 bronze badges 3
  • 1 Your question makes no sense to me. Starting with <xsl:apply-templates select="Scroll0"/> (there is no Scroll0 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:23
  • In what version of HTML would you put a span element as a child of a table element? Why would you need (Muenchian) grouping if the sample data you show has two distinct rows with distinct GUEST_USERIDs? – Martin Honnen Commented Jan 2 at 22:49
  • I'm not sure. I am still new to this. I was wondering if I messed up with the title. But it's not producing two tables even though there are two distinct user IDs. The program I use created Scroll0 as the beginning point. I thought since it was just showing the first User with their Access and Description, that I would need Muenchian to do the same for the second ID. – MPourier Commented Jan 3 at 14:42
Add a comment  | 

1 Answer 1

Reset to default 0

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:

转载请注明原文地址:http://anycun.com/QandA/1746096416a91615.html