php - Using XSLT to create a well formatted nested table from unknown XML -
the task given: boss wants me create xslt takes xml of unknown structure, , put nested table (tag names table headers) without repeating table headers possible. able wants (the table )
the question: have worked xslt's few days (have gone through few tutorials , played bit), if can point me in direction on find information me problem, appreciated.
environment data: working xslt , php (dom objects). boss wants me become companies xslt expert, if possible through pure xslt, appreciated.
additional info: @ request of people responding, additional info (code) below.the task turn xml snippet below table below displaying. unfortunately, code had in state of flux @ moment, not posting (if question still open when stable again, post it).
xml snippet:
<root> <request> <details> <columnname>name1</columnname> <operator></operator> <value>val</value> <seq>1</seq> </details> </request> <request> <details> <columnname>name2</columnname> <operator>op</operator> <value>val</value> <seq>2</seq> </details> </request> <request> <details> <columnname>name3</columnname> <value>val</value> <seq>3</seq> </details> </request> <response> <details> <columnname>name4</columnname> <value>val</value> <seq>4</seq> </details> </response> </root>
desired output
<table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>root</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>request</th> <th>response</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>details</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>columnname</th> <th>operator</th> <th>value</th> <th>seq</th> </tr> <tr> <td>name1</td> <td></td> <td>val</td> <td>1</td> </tr> <tr> <td>name2</td> <td>op</td> <td>val</td> <td>2</td> </tr> <tr> <td>name3</td> <td></td> <td>val</td> <td>3</td> </tr> </table> </td> </tr> </table> </td> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>details</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>columnname</th> <th>value</th> <th>seq</th> </tr> <tr> <td>name4</td> <td>val</td> <td>4</td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table>
response michael.hor257k: this.
<table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>root</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>parent</th> <th>uncle</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>child</th> <th>nephew</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>string</th> <th>number</th> <th>grandchild</th> <th>date</th> </tr> <tr> <td>a</td> <td></td> <td></td> <td></td> </tr> <tr> <td>b</td> <td></td> <td></td> <td></td> </tr> <tr> <td>c</td> <td>1</td> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>string</th> <th>substring</th> <th>number</th> </tr> <tr> <td>dd</td> <td>ee</td> <td>33</td> </tr> </table> </td> <td></td> </tr> <tr> <td></td> <td>2</td> <td></td> <td></td> </tr> <tr> <td>f</td> <td></td> <td></td> <td>2015-02-12</td> </tr> </table> </td> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>string</th> </tr> <tr> <td>g</td> </tr> </table> </td> </tr> </table> </td> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>niece</th> </tr> <tr> <td> <table border="1" style="border-collapse:collapse;width:100%"> <tr> <th>string</th> </tr> <tr> <td>h</td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table>
as said in comments, not going simple. basically, want remove duplicate nodes have same path (where path calculated using node names) , display resulting hierarchy.
this requires making pre-processing pass assign nodes path. need provide each node parent path - can called later new parent (which formerly uncle or great-uncle or...).
in second - , final - step applying muenchian grouping result of first pass, leaving distinct nodes path.
in example processing elements, , result presented unordered list.
xslt 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="node-by-path" match="node" use="@path" /> <xsl:key name="node-by-parent-path" match="node" use="@parent-path" /> <xsl:template match="/"> <!-- first-pass --> <xsl:variable name="first-pass"> <xsl:apply-templates select="*" mode="firstpass"/> </xsl:variable> <!-- output --> <ul> <xsl:apply-templates select="exsl:node-set($first-pass)/node[@parent-path='']" /> </ul> </xsl:template> <xsl:template match="*" mode="firstpass"> <xsl:variable name="parent-path"> <xsl:for-each select="ancestor::*"> <xsl:value-of select="concat('/', name())"/> </xsl:for-each> </xsl:variable> <node name="{name()}" parent-path="{$parent-path}" path="{concat($parent-path, '/', name())}"> <xsl:apply-templates select="*" mode="firstpass"/> </node> </xsl:template> <xsl:template match="node"> <li> <xsl:value-of select="@name"/> <xsl:variable name="next" select="key('node-by-parent-path', @path)" /> <xsl:if test="$next"> <ul> <xsl:apply-templates select="$next[count(. | key('node-by-path', @path)[1]) = 1]"/> </ul> </xsl:if> </li> </xsl:template> </xsl:stylesheet>
test input xml
<root> <parent> <child> <string>a</string> <string>b</string> </child> <child> <string>c</string> <number>1</number> <number>2</number> <grandchild> <string>dd</string> <substring>ee</substring> <number>33</number> </grandchild> </child> </parent> <parent> <child> <string>f</string> <date>2015-02-12</date> </child> <nephew> <string>g</string> </nephew> </parent> <uncle> <niece> <string>h</string> </niece> </uncle> </root>
result
<?xml version="1.0" encoding="utf-8"?> <ul> <li>root<ul> <li>parent<ul> <li>child<ul> <li>string</li> <li>number</li> <li>grandchild<ul> <li>string</li> <li>substring</li> <li>number</li> </ul> </li> <li>date</li> </ul> </li> <li>nephew<ul> <li>string</li> </ul> </li> </ul> </li> <li>uncle<ul> <li>niece<ul> <li>string</li> </ul> </li> </ul> </li> </ul> </li> </ul>
rendered
Comments
Post a Comment