I have a question about how to use XSL (Extensible Stylesheet Language) to transform some basic XML into an unordered list while retaining the nesting. Here is a sample script containing the XML and the XSL which I have tried.
Code:
#!/usr/bin/python3
import lxml.etree as et
outline = '''<?xml version="1.0" encoding="UTF-8"?>
<xml>
<o text="1">
<o text="1.A" />
<o text="1.B" />
<o text="1.C" />
</o>
<o text="2">
<o text="2.A">
<o text="2.A.1" />
<o text="2.A.2" />
</o>
<o text="2.B">
<o text="2.B.1" />
<o text="2.B.2" />
</o>
<o text="2.C" />
</o>
</xml>
'''
xsl = '''
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<ul>
<xsl:for-each select=".//o">
<li>
<xsl:value-of select="@text" />
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
'''
dom = et.fromstring(outline.encode())
xslt = et.XML(xsl)
transform = et.XSLT(xslt)
dom2 = transform(dom)
html = et.tostring(dom2,pretty_print=True)
print(f"{html}")
That results in a flat list with a single level:
Code:
<ul>\n <li>1</li>\n <li>1.A</li>\n <li>1.B</li>\n <li>1.C</li>\n <li>2</li>\n <li>2.A</li>\n <li>2.A.1</li>\n <li>2.A.2</li>\n <li>2.B</li>\n <li>2.B.1</li>\n <li>2.B.2</li>\n <li>2.C</li>\n</ul>\n
I've tried a lot of variants but don't fully understand XSL and can't get past a flat list.
What I am hoping to figure out is how to preserve the nested aspects. The expected result would be this instead:
Code:
<ul>\n <li>1\n <ul>\n <li>1.A</li>\n <li>1.B</li>\n <li>1.C</li>\n </ul>\n </li>\n <li>2\n <ul>\n <li>2.A\n <ul>\n <li>2.A.1</li>\n <li>2.A.2</li>\n </ul>\n </li>\n <li>2.B\n <ul>\n <li>2.B.1</li>\n <li>2.B.2</li>\n </ul>\n </li>\n <li>2.C</li>\n </ul>\n</li>\n </ul>\n
How should the XSL look to achieve that?