简体   繁体   中英

Transform XML to HTML using XSL issue selecting dynamically all child nodes based on attribute value

I am trying to use XSL to present an XML report as HTML. XSL does not return errors as per the format or anything(checked using Altova XMLSpy application) but does not provide the correct html table I am expecting. Below is my XML code and my XSL code. What I need, because my XML node/tag <row></row> does not always have <key> tags or <value> tags but it can be different for time to time, is to list all those child tags using xsl to html table dynamically whatever the case is. For example below I want to produce an HTML table with rows the numbers of the rows and for each row to have the columns listed which will be in this case:

column 1 = Institution_Id
column 2= Section
column 3= CATEGORY
column 4= SUBCATEGORY
column 5= ITEM
*column 6= VALUE
column7= SHORTCODE

and the rows should be

1
2
.
. 8
9
.
.
.

ps: * as you can see from the xml the column 6 is not the same tag name as the rest <key> vs <value> this can be done with other cases like have <key> vs <item> .

XML code:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="ParamStyleSTAVROS.xsl"?>
<Report>
<Header></Header>
<Results Property="Comparison Results">
    <row number="1" type="equal">
        <key column="Institution_Id" left="CNTR"/>
        <key column="Institution_Id" right="CNTR"/>
    </row>
    <row number="1" type="equal">
        <key column="SECTION" left="AMEX"/>
        <key column="SECTION" right="AMEX"/>
    </row>
    <row number="1" type="equal">
        <key column="CATEGORY" left="reason codes"/>
        <key column="CATEGORY" right="reason codes"/>
    </row>
    <row number="1" type="equal">
        <key column="SUBCATEGORY" left="exception reason codes"/>
        <key column="SUBCATEGORY" right="exception reason codes"/>
    </row>
    <row number="1" type="equal">
        <key column="ITEM" left="3000 - Lost card"/>
        <key column="ITEM" right="3000 - Lost card"/>
    </row>
    <row number="1" type="equal">
        <value column="VALUE" left="3000"/>
        <value column="VALUE" right="3000.0"/>
    </row>
    <row number="1" type="equal">
        <key column="SHORTCODE" left="DEFP"/>
        <key column="SHORTCODE" right="DEFP"/>
    </row>
    <row number="2" type="equal">
        <key column="Institution_Id" left="CNTR"/>
        <key column="Institution_Id" right="CNTR"/>
    </row>
    <row number="2" type="equal">
        <key column="SECTION" left="AMEX"/>
        <key column="SECTION" right="AMEX"/>
    </row>
    <row number="2" type="equal">
        <key column="CATEGORY" left="reason codes"/>
        <key column="CATEGORY" right="reason codes"/>
    </row>
    <row number="2" type="equal">
        <key column="SUBCATEGORY" left="exception reason codes"/>
        <key column="SUBCATEGORY" right="exception reason codes"/>
    </row>
    <row number="2" type="equal">
        <key column="ITEM" left="3001 - Stolen Card"/>
        <key column="ITEM" right="3001 - Stolen Card"/>
    </row>
    <row number="2" type="equal">
        <value column="VALUE" left="3001"/>
        <value column="VALUE" right="3001.0"/>
    </row>
    <row number="2" type="equal">
        <key column="SHORTCODE" left="DEFP"/>
        <key column="SHORTCODE" right="DEFP"/>
    </row>
    .
    .
    .
    .
    .
    .
    <row number="8" type="orphaned">
        <key column="Institution_Id" left=""/>
        <key column="Institution_Id" right="CNTR"/>
    </row>
    <row number="8" type="orphaned">
        <key column="SECTION" left=""/>
        <key column="SECTION" right="AMEX"/>
    </row>
    <row number="8" type="orphaned">
        <key column="CATEGORY" left=""/>
        <key column="CATEGORY" right="Statistics"/>
    </row>
    <row number="8" type="orphaned">
        <key column="SUBCATEGORY" left=""/>
        <key column="SUBCATEGORY" right="Product"/>
    </row>
    <row number="8" type="orphaned">
        <key column="ITEM" left=""/>
        <key column="ITEM" right="product line"/>
    </row>
    <row number="8" type="orphaned">
        <value column="VALUE" left=""/>
        <value column="VALUE" right="NULL"/>
    </row>
    <row number="8" type="orphaned">
        <key column="SHORTCODE" left=""/>
        <key column="SHORTCODE" right="DEFP"/>
    </row>
    <row number="9" type="orphaned">
        <key column="Institution_Id" left=""/>
        <key column="Institution_Id" right="CNTR"/>
    </row>
    <row number="9" type="orphaned">
        <key column="SECTION" left=""/>
        <key column="SECTION" right="AMEX"/>
    </row>
    <row number="9" type="orphaned">
        <key column="CATEGORY" left=""/>
        <key column="CATEGORY" right="Statistics"/>
    </row>
    <row number="9" type="orphaned">
        <key column="SUBCATEGORY" left=""/>
        <key column="SUBCATEGORY" right="Product"/>
    </row>
    <row number="9" type="orphaned">
        <key column="ITEM" left=""/>
        <key column="ITEM" right="product name"/>
    </row>
    <row number="9" type="orphaned">
        <value column="VALUE" left=""/>
        <value column="VALUE" right="NULL"/>
    </row>
    <row number="9" type="orphaned">
        <key column="SHORTCODE" left=""/>
        <key column="SHORTCODE" right="DEFP"/>
    </row>
    .
    .
    .
    .
    .
    .
    .
</Results>
</Report>

XSL code:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/Report/Header">

<html>
<style>
h1{
font-family: Gill Sans, Verdana;
font-size: 11px;
line-height: px;
text-transform: uppercase;
letter-spacing: 2px;
font-weight: bold;
}
table,th,td{
font-family: Gill Sans, Verdana;
text-transform: uppercase;
letter-spacing: 2px;
font-weight: bold;
border: 1px solid black;
border-collapse: collapse;
width:100%;
}
td{
font-size: 11px;
padding:5px;
}
th{
font-size: 18px;
height: 20px;
padding:5px;
background-color: yellow;
color: black;
}


</style>

<head>
    <h1>Comparison Report Information</h1>
        <table>
            <th>ReportCreated</th>
            <th>Product</th>
            <th>PrimaryDB</th>
            <th>PrimaryDBMS</th>
            <th>SecondaryDB</th>    
            <th>SecondaryDBMS</th>  
        <tr>
            <xsl:for-each select="Property">
            <td>
            <xsl:value-of select="@*"></xsl:value-of>
            </td>
            </xsl:for-each>
        </tr>

        </table>
</head>
<body>

        <h1>Results</h1>
        <br></br>
<table>

    <xsl:for-each select="row/@number">
        <tr>
            <xsl:for-each select="row">
                <th>
                    <xsl:value-of select="@*"></xsl:value-of>       
                </th>
            </xsl:for-each>
        </tr>

        <tr>
            <td>
                <xsl:value-of select="."></xsl:value-of>        
            </td>
        </tr>
    </xsl:for-each>
</table>

</body>
 </html>
</xsl:template>
</xsl:stylesheet>

To solve this, you can make use of a technique called Muenchian Grouping . This can be used to get the distinct columns, and also to group the row elements by their number attribute.

To get the distinct column names, first define a key like this (This assumes there will always be a column attribute

<xsl:key name="columns" match="row/*" use="@column" />

And to use it, to get the distinct column names, do this...

<xsl:variable 
     name="columns" 
     select="//row/*[generate-id() = generate-id(key('columns', @column)[1])]/@column"/>

Similarly for rows, you need to group the row element by number, so you define a key like this

<xsl:key name="rows" match="row" use="@number" />

Then, to get the row elements with the first occurence of a number, do this

<xsl:for-each select="row[generate-id() = generate-id(key('rows', @number)[1])]">

Then, to get the row elements that will make up the table row, use the key to get all rows with the same number

<xsl:variable name="row" select="key('rows', @number)" />

Try this XSLT for starters:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>

<xsl:key name="columns" match="row/*" use="@column" />
<xsl:key name="rows" match="row" use="@number" />

<xsl:template match="/Report/Results">
    <xsl:variable name="columns" select="//row/*[generate-id() = generate-id(key('columns', @column)[1])]/@column"/>
    <html>
    <head>
        <title>Table</title>
    </head>
    <body>
    <table>
        <thead>
        <tr>
            <th>Row Number</th>
            <xsl:for-each select="$columns">
                <th><xsl:value-of select="." /></th>
            </xsl:for-each>
        </tr>
        </thead>
        <xsl:for-each select="row[generate-id() = generate-id(key('rows', @number)[1])]">
            <xsl:variable name="row" select="key('rows', @number)" />
            <tr>
                <td>
                    <xsl:value-of select="@number" />
                </td>
                <xsl:for-each select="$columns">
                    <td>
                        <xsl:value-of select="$row/*[@column = current()]/@right" />
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
    </table>
    </body>
    </html>
</xsl:template>
</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM