Subject: [xsl] WG: Nested Grouping of "flat" input From: Thomas Zöchling <thomas.zoechling@xxxxxx> Date: Thu, 9 Dec 2004 12:08:13 +0100 |
Hi List! I am working on a bookmark manager, that is built around XBEL (http://pyxml.sourceforge.net/topics/xbel/). The server-side part of our application needs to store the bookmark data in a relational database. But as XBEL defines a nested hierarchy, which cannot be stored in the database directly, we had to introduce a flat version of the XBEL data. Now our problem is, that we need to go the other way round, and extract the path of a bookmark from our flat xml file, and restore the XBEL hierarchy from it. User( browser) -> XBEL -> flat format -> database -> flat -> XBEL -> all other formats Summary: Create a XML structured hierarchy from a path. Examples: XBEL: <?xml version="1.0" encoding="UTF-8"?> <xbel version="1.0"> <title>Bookmarks</title> <older folded="yes"> <title>Sample2</title> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"><title>Mozilla Firefox Startseite</title></bookmark> </folder> <folder folded="yes"> <title>Sample</title> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"><title>Test</title></bookmark> <folder folded="yes"> <title>FolderInSample</title> </folder> </folder> <folder folded="yes"> <title>Bookmarks Toolbar Folder</title> <bookmark href="http://slashdot.org/"><title>Slashdot: News for nerds, stuff that matters</title></bookmark> <bookmark href="http://www.heise.de/"><title>heise online</title></bookmark> <bookmark href="http://futurezone.orf.at/"><title>ORF ON Futurezone</title></bookmark> </folder> </xbel> Flat XBEL: <?xml version="1.0" encoding="utf-8"?> <xbelflat version="1.0"> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="Mozilla Firefox Startseite" pfad="Bookmarks/Sample2/"></bookmark> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="Test" pfad="Bookmarks/Sample/"></bookmark> <bookmark href="http://slashdot.org/" name="Slashdot: News for nerds, stuff that matters" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> <bookmark href="http://www.heise.de/" name="heise online" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> <bookmark href="http://futurezone.orf.at/" name="ORF ON Futurezone" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> </xbelflat> The xbelflat should be transformed back to XBEL: What I can now: - Split the path (@pfad) and output it in folders - Group the bookmarks What I cannot: - Do the whole transform in one stylesheet - Recreate the correct hierarchy (currently everything is flat grouped) XSLT stylesheets: Extracts the folder Names from the @pfad (=path) attribute <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:template name="root" match="xbelflat"> <xbelflat version="1.0"> <xsl:call-template name="bm"></xsl:call-template> </xbelflat> </xsl:template> <xsl:template name="bm"> <xsl:for-each select="bookmark"> <xsl:apply-templates/> <xsl:call-template name="links"> <xsl:with-param name="str" select="@pfad"/> <xsl:with-param name="pos" select="position()-1"/> </xsl:call-template> </xsl:for-each> <xsl:apply-templates/> </xsl:template> <xsl:template name="links"> <xsl:param name="str"/> <xsl:param name="pos"/> <xsl:variable name="bmName" select="@name"/> <xsl:if test="position() != 1 "> </xsl:if> <xsl:choose> <xsl:when test="contains($str,'/') and $bmName!=substring-before($str,'/')"> <folder> <xsl:attribute name="pfad"><xsl:value-of select="substring-before($str,'/')"/></xsl:attribute> <xsl:call-template name="links"> <xsl:with-param name="str" select="substring-after($str,'/')"/> </xsl:call-template> </folder> </xsl:when> <xsl:otherwise> <xsl:attribute name="href"><xsl:value-of select="@href"></xsl:value-of></xsl:attribute><xsl:value-of select="following-sibling"/> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Output of the above <?xml version="1.0" encoding="UTF-16"?> <xbelflat version="1.0"> <folder pfad="Bookmarks"> <folder pfad="Sample2" href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Sample" href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://slashdot.org/"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://www.heise.de/"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://futurezone.orf.at/"></folder> </folder> </xbelflat> Second Stylesheet: Groups the Bookmarks (But any structure information is lost here) <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="distinct" match="folder" use="@pfad"/> <xsl:template match="/"> <xbel version="1.0"> <!--<xsl:for-each select="/xbelflat/folder/folder/folder[generate-id(.) = generate-id(key('distinct',@pfad))]"> --> <xsl:for-each select="xbelflat//folder[generate-id(.) = generate-id(key('distinct',@pfad))]"> <folder> <xsl:value-of select="@pfad"/> <xsl:variable name="currPath"> <xsl:value-of select="@pfad"/> </xsl:variable> <xsl:variable name="lstBookmark" select="//folder[@pfad=$currPath]"/> <xsl:call-template name="DistinctedBookmarks"> <xsl:with-param name="lstBookmark" select="$lstBookmark" /> </xsl:call-template> </folder> </xsl:for-each> </xbel> </xsl:template> <xsl:template name="DistinctedBookmarks"> <xsl:param name="lstBookmark"/> <xsl:for-each select="$lstBookmark"> <xsl:if test="@href!=''"> <xsl:element name="bookmark"> <xsl:attribute name="href"><xsl:value-of select="@href"/></xsl:attribute> <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute> </xsl:element> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> Output: Hi List! I am working on a bookmark manager, that is built around XBEL (http://pyxml.sourceforge.net/topics/xbel/). The server-side part of our application needs to store the bookmark data in a relational database. But as XBEL defines a nested hierarchy, which cannot be stored in the database directly, we had to introduce a flat version of the XBEL data. Now our problem is, that we need to go the other way round, and extract the path of a bookmark from our flat xml file, and restore the XBEL hierarchy from it. User( browser) -> XBEL -> flat format -> database -> flat -> XBEL -> all other formats Summary: Create a XML structured hierarchy from a path. Examples: XBEL: <?xml version="1.0" encoding="UTF-8"?> <xbel version="1.0"> <title>Bookmarks</title> <older folded="yes"> <title>Sample2</title> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"><title>Mozilla Firefox Startseite</title></bookmark> </folder> <folder folded="yes"> <title>Sample</title> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"><title>Test</title></bookmark> <folder folded="yes"> <title>FolderInSample</title> </folder> </folder> <folder folded="yes"> <title>Bookmarks Toolbar Folder</title> <bookmark href="http://slashdot.org/"><title>Slashdot: News for nerds, stuff that matters</title></bookmark> <bookmark href="http://www.heise.de/"><title>heise online</title></bookmark> <bookmark href="http://futurezone.orf.at/"><title>ORF ON Futurezone</title></bookmark> </folder> </xbel> Flat XBEL: <?xml version="1.0" encoding="utf-8"?> <xbelflat version="1.0"> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="Mozilla Firefox Startseite" pfad="Bookmarks/Sample2/"></bookmark> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="Test" pfad="Bookmarks/Sample/"></bookmark> <bookmark href="http://slashdot.org/" name="Slashdot: News for nerds, stuff that matters" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> <bookmark href="http://www.heise.de/" name="heise online" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> <bookmark href="http://futurezone.orf.at/" name="ORF ON Futurezone" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> </xbelflat> The xbelflat should be transformed back to XBEL: What I can now: - Split the path (@pfad) and output it in folders - Group the bookmarks What I cannot: - Do the whole transform in one stylesheet - Recreate the correct hierarchy (currently everything is flat grouped) XSLT stylesheets: Extracts the folder Names from the @pfad (=path) attribute <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:template name="root" match="xbelflat"> <xbelflat version="1.0"> <xsl:call-template name="bm"></xsl:call-template> </xbelflat> </xsl:template> <xsl:template name="bm"> <xsl:for-each select="bookmark"> <xsl:apply-templates/> <xsl:call-template name="links"> <xsl:with-param name="str" select="@pfad"/> <xsl:with-param name="pos" select="position()-1"/> </xsl:call-template> </xsl:for-each> <xsl:apply-templates/> </xsl:template> <xsl:template name="links"> <xsl:param name="str"/> <xsl:param name="pos"/> <xsl:variable name="bmName" select="@name"/> <xsl:if test="position() != 1 "> </xsl:if> <xsl:choose> <xsl:when test="contains($str,'/') and $bmName!=substring-before($str,'/')"> <folder> <xsl:attribute name="pfad"><xsl:value-of select="substring-before($str,'/')"/></xsl:attribute> <xsl:call-template name="links"> <xsl:with-param name="str" select="substring-after($str,'/')"/> </xsl:call-template> </folder> </xsl:when> <xsl:otherwise> <xsl:attribute name="href"><xsl:value-of select="@href"></xsl:value-of></xsl:attribute><xsl:value-of select="following-sibling"/> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Output of the above <?xml version="1.0" encoding="UTF-16"?> <xbelflat version="1.0"> <folder pfad="Bookmarks"> <folder pfad="Sample2" href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Sample" href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://slashdot.org/"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://www.heise.de/"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://futurezone.orf.at/"></folder> </folder> </xbelflat> Second Stylesheet: Groups the Bookmarks (But any structure information is lost here) <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="distinct" match="folder" use="@pfad"/> <xsl:template match="/"> <xbel version="1.0"> <!--<xsl:for-each select="/xbelflat/folder/folder/folder[generate-id(.) = generate-id(key('distinct',@pfad))]"> --> <xsl:for-each select="xbelflat//folder[generate-id(.) = generate-id(key('distinct',@pfad))]"> <folder> <xsl:value-of select="@pfad"/> <xsl:variable name="currPath"> <xsl:value-of select="@pfad"/> </xsl:variable> <xsl:variable name="lstBookmark" select="//folder[@pfad=$currPath]"/> <xsl:call-template name="DistinctedBookmarks"> <xsl:with-param name="lstBookmark" select="$lstBookmark" /> </xsl:call-template> </folder> </xsl:for-each> </xbel> </xsl:template> <xsl:template name="DistinctedBookmarks"> <xsl:param name="lstBookmark"/> <xsl:for-each select="$lstBookmark"> <xsl:if test="@href!=''"> <xsl:element name="bookmark"> <xsl:attribute name="href"><xsl:value-of select="@href"/></xsl:attribute> <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute> </xsl:element> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> Output: Hi List! I am working on a bookmark manager, that is built around XBEL (http://pyxml.sourceforge.net/topics/xbel/). The server-side part of our application needs to store the bookmark data in a relational database. But as XBEL defines a nested hierarchy, which cannot be stored in the database directly, we had to introduce a flat version of the XBEL data. Now our problem is, that we need to go the other way round, and extract the path of a bookmark from our flat xml file, and restore the XBEL hierarchy from it. User( browser) -> XBEL -> flat format -> database -> flat -> XBEL -> all other formats Summary: Create a XML structured hierarchy from a path. Examples: XBEL: <?xml version="1.0" encoding="UTF-8"?> <xbel version="1.0"> <title>Bookmarks</title> <older folded="yes"> <title>Sample2</title> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"><title>Mozilla Firefox Startseite</title></bookmark> </folder> <folder folded="yes"> <title>Sample</title> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"><title>Test</title></bookmark> <folder folded="yes"> <title>FolderInSample</title> </folder> </folder> <folder folded="yes"> <title>Bookmarks Toolbar Folder</title> <bookmark href="http://slashdot.org/"><title>Slashdot: News for nerds, stuff that matters</title></bookmark> <bookmark href="http://www.heise.de/"><title>heise online</title></bookmark> <bookmark href="http://futurezone.orf.at/"><title>ORF ON Futurezone</title></bookmark> </folder> </xbel> Flat XBEL: <?xml version="1.0" encoding="utf-8"?> <xbelflat version="1.0"> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="Mozilla Firefox Startseite" pfad="Bookmarks/Sample2/"></bookmark> <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="Test" pfad="Bookmarks/Sample/"></bookmark> <bookmark href="http://slashdot.org/" name="Slashdot: News for nerds, stuff that matters" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> <bookmark href="http://www.heise.de/" name="heise online" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> <bookmark href="http://futurezone.orf.at/" name="ORF ON Futurezone" pfad="Bookmarks/Bookmarks Toolbar Folder/"></bookmark> </xbelflat> The xbelflat should be transformed back to XBEL: What I can now: - Split the path (@pfad) and output it in folders - Group the bookmarks What I cannot: - Do the whole transform in one stylesheet - Recreate the correct hierarchy (currently everything is flat grouped) XSLT stylesheets: Extracts the folder Names from the @pfad (=path) attribute <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:template name="root" match="xbelflat"> <xbelflat version="1.0"> <xsl:call-template name="bm"></xsl:call-template> </xbelflat> </xsl:template> <xsl:template name="bm"> <xsl:for-each select="bookmark"> <xsl:apply-templates/> <xsl:call-template name="links"> <xsl:with-param name="str" select="@pfad"/> <xsl:with-param name="pos" select="position()-1"/> </xsl:call-template> </xsl:for-each> <xsl:apply-templates/> </xsl:template> <xsl:template name="links"> <xsl:param name="str"/> <xsl:param name="pos"/> <xsl:variable name="bmName" select="@name"/> <xsl:if test="position() != 1 "> </xsl:if> <xsl:choose> <xsl:when test="contains($str,'/') and $bmName!=substring-before($str,'/')"> <folder> <xsl:attribute name="pfad"><xsl:value-of select="substring-before($str,'/')"/></xsl:attribute> <xsl:call-template name="links"> <xsl:with-param name="str" select="substring-after($str,'/')"/> </xsl:call-template> </folder> </xsl:when> <xsl:otherwise> <xsl:attribute name="href"><xsl:value-of select="@href"></xsl:value-of></xsl:attribute><xsl:value-of select="following-sibling"/> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Output of the above <?xml version="1.0" encoding="UTF-16"?> <xbelflat version="1.0"> <folder pfad="Bookmarks"> <folder pfad="Sample2" href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Sample" href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://slashdot.org/"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://www.heise.de/"></folder> </folder> <folder pfad="Bookmarks"> <folder pfad="Bookmarks Toolbar Folder" href="http://futurezone.orf.at/"></folder> </folder> </xbelflat> Second Stylesheet: Groups the Bookmarks (But any structure information is lost here) <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="distinct" match="folder" use="@pfad"/> <xsl:template match="/"> <xbel version="1.0"> <!--<xsl:for-each select="/xbelflat/folder/folder/folder[generate-id(.) = generate-id(key('distinct',@pfad))]"> --> <xsl:for-each select="xbelflat//folder[generate-id(.) = generate-id(key('distinct',@pfad))]"> <folder> <xsl:value-of select="@pfad"/> <xsl:variable name="currPath"> <xsl:value-of select="@pfad"/> </xsl:variable> <xsl:variable name="lstBookmark" select="//folder[@pfad=$currPath]"/> <xsl:call-template name="DistinctedBookmarks"> <xsl:with-param name="lstBookmark" select="$lstBookmark" /> </xsl:call-template> </folder> </xsl:for-each> </xbel> </xsl:template> <xsl:template name="DistinctedBookmarks"> <xsl:param name="lstBookmark"/> <xsl:for-each select="$lstBookmark"> <xsl:if test="@href!=''"> <xsl:element name="bookmark"> <xsl:attribute name="href"><xsl:value-of select="@href"/></xsl:attribute> <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute> </xsl:element> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> Output: <?xml version="1.0" encoding="UTF-16"?><xbel version="1.0"> <folder>Bookmarks</folder> <folder>Sample2 <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="" /></folder> <folder>Sample <bookmark href="http://www.google.at/firefox?client=firefox-a&rls=org.mozilla:de-D E:official" name="" /></folder> <folder>Bookmarks Toolbar Folder<bookmark href="http://slashdot.org/" name="" /> <bookmark href="http://www.heise.de/" name="" /> <bookmark href="http://futurezone.orf.at/" name="" /></folder> </xbel> How can I get back a Tee structure? Bookmarks Sample2 Sample . BookmarkToolbarFolder . . Thanks in advance Thomas
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] XSLT 2.0 - Combining Node, Jarno.Elovirta | Thread | AW: [xsl] XSLT 2.0 - Combining Node, Huditsch Roman |
[xsl] XSL-FO double line border, Ranjan K. Baisak | Date | RE: [xsl] XSLT 2.0 - Combining Node, Jarno.Elovirta |
Month |