Forum Moderators: open

Message Too Old, No Replies

Poor XML, but need XSLT on it

Need help with XSLT for XML data poorly written

         

Malc

5:34 pm on Jun 7, 2006 (gmt 0)

10+ Year Member



Hi. I have the following XML code that I need to create an XSLT to translate into HTML from. The XML is poorly written and I have no control over it atm. Any help would be appreciated. I have included my XSLT that I have so far. It grabs the table headers fine, but getting the actual data (the select = ".") causes all the cells to be concatenated as one cell. I.e, if I have 4 cells of "1", "2", "3", and "4", only the first cell is populated, with "1234".

XML extract:

<?xml version="1.0" encoding="utf-8"?>
<CTestResults xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Tests>
<Description>ABSENTEEAPPLICATIONS - NameMiddle has invalid characters</Description>
<Test>SELECT top 20 AbsenteeApplicationID, VoterID, NameMiddle FROM AbsenteeApplications
WHERE NameMiddle = ''
OR NameMiddle LIKE '%[ ,-$%\^\&amp;*\(\)=\+\_\!\\\/\?\&lt;\&gt;\.`\~]%'
OR NameMiddle LIKE '% JR%' OR NameMiddle LIKE '% SR%' OR NameMiddle LIKE '% II%' OR NameMiddle LIKE '% III%' OR NameMiddle LIKE '% IV%' </Test>
<Passed>false</Passed>
<Results>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="Table1">
<xs:complexType>
<xs:sequence>
<xs:element name="AbsenteeApplicationID" type="xs:int" minOccurs="0" />
<xs:element name="VoterID" type="xs:int" minOccurs="0" />
<xs:element name="NameMiddle" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet>
<Table1 diffgr:id="Table11" msdata:rowOrder="0">
<AbsenteeApplicationID>4022001</AbsenteeApplicationID>
<VoterID>4022071</VoterID>
<NameMiddle>J.</NameMiddle>
</Table1>
<Table1 diffgr:id="Table12" msdata:rowOrder="1">
<AbsenteeApplicationID>4022002</AbsenteeApplicationID>
<VoterID>4022072</VoterID>
<NameMiddle>M.</NameMiddle>
</Table1>
<Table1 diffgr:id="Table13" msdata:rowOrder="2">
<AbsenteeApplicationID>4022003</AbsenteeApplicationID>
<VoterID>4022102</VoterID>
<NameMiddle>L.</NameMiddle>
</Table1>
<Table1 diffgr:id="Table14" msdata:rowOrder="3">
<AbsenteeApplicationID>4022004</AbsenteeApplicationID>
<VoterID>4022106</VoterID>
<NameMiddle>B.</NameMiddle>
</Table1>
<Table1 diffgr:id="Table15" msdata:rowOrder="4">
<AbsenteeApplicationID>4022006</AbsenteeApplicationID>
<VoterID>4022159</VoterID>
<NameMiddle>A.</NameMiddle>
</Table1>
</NewDataSet>
</diffgr:diffgram>
</Results>
</Tests>
</CTestResults>

XSLT:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<head>
<style type="text/css">
body {background-color: rgb(250,210,250)}
.h1 {font-family: "courier new", monospace}
.h1 {color: blue}
.h2 {font-family: "courier new", monospace}
.h2 {color: darkblue}
p.sql {font-family: "courier new", monospace}
p.sql {color: green}
p.sql {font-weight: bold}
</style>
</head>
<body>
<h1>SVU FAILED Results</h1>
<xsl:for-each select="CTestResults/Tests">
<xsl:if test="Passed!= 'true'">
<span class="h1">
<br>Description: <xsl:value-of select="Description"/></br>
</span>
<span class="h2">
<br>Test: <xsl:value-of select="Test"/></br>
</span>
<table border="1">
<tr>
<xsl:for-each select="Results/xs:schema/xs:element/xs:complexType/xs:choice/xs:element/xs:complexType/xs:sequence/xs:element">
<td><xsl:value-of select="@name"/></td>
</xsl:for-each>
</tr>
<xsl:for-each select="Results/diffgr:diffgram/NewDataSet/Table1">
<tr>
<td><xsl:value-of select="."/></td>
</tr>
</xsl:for-each>
</table>
</xsl:if>

</xsl:for-each>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

Thanks again for any help! Sorry about the no-indenting, wasn't sure how to preserve it.
-Malc

choster

7:11 pm on Jun 13, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Malc, welcome to WebmasterWorld.

You have

<xsl:for-each select="Results/diffgr:diffgram/NewDataSet/Table1">
<tr>
<td><xsl:value-of select="."/></td>
</tr>
</xsl:for-each>

which asks for the text() value of each <Table1>, so you'll get either a blank cell or 40220014022071J. for your result. You should request the subelements individually, for instance

<xsl:for-each select="Results/diffgr:diffgram/NewDataSet/Table1">
<tr>
<td><xsl:value-of select="AbsenteeApplicationID"/></td>
<td><xsl:value-of select="VoterID"/></td>
<td><xsl:value-of select="NameMiddle"/></td>
</tr>
</xsl:for-each>
but perhaps you want to genericize it, in which case I'd also suggest for ease of maintenance that you replace the <xsl:for-each>s with <xsl:apply-templates>, e.g.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<style type="text/css">
body {background-color: rgb(250,210,250)}
.h1 {font-family: "courier new", monospace}
.h1 {color: blue}
.h2 {font-family: "courier new", monospace}
.h2 {color: darkblue}
p.sql {font-family: "courier new", monospace}
p.sql {color: green}
p.sql {font-weight: bold}
</style>
</head>
<body>
<h1>SVU FAILED Results</h1>
<xsl:apply-templates select="CTestResults/Tests[Passed!= 'true']"/>
</body>
</html>
</xsl:template>

<xsl:template match="Tests">
<span class="h1">
<br>Description: <xsl:value-of select="Description"/>
</br>
</span>
<span class="h2">
<br>Test: <xsl:value-of select="Test"/>
</br>
</span>
<table border="1">
<tr>
<xsl:apply-templates select="Results/xs:schema/xs:element/xs:complexType/xs:choice/xs:element/xs:complexType/xs:sequence/xs:element"/>
</tr>
<xsl:apply-templates select="Results/diffgr:diffgram/NewDataSet/Table1" />
</table>
</xsl:template>

<xsl:template match="xs:element">
<td>
<xsl:value-of select="@name"/>
</td>
</xsl:template>

<xsl:template match="Table1">
<tr>
<xsl:for-each select="*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>

Malc

9:44 pm on Jun 13, 2006 (gmt 0)

10+ Year Member



Hye, thanks! That worked beautifully. I changed the <td> elements to <th> for the template match of 'xs:element', but nice!

Yes, it needed to be generaliced. I have no way of knowing the element names ahead of time, they could be anything, because they are taken from various databases.

Thanks again for your help!
Malc