[z3-checkins] r55528 - in z3/deliverance/sandboxes/paul/dvng: . var
paul at codespeak.net
paul at codespeak.net
Tue Jun 3 21:01:24 CEST 2008
Author: paul
Date: Tue Jun 3 21:01:20 2008
New Revision: 55528
Added:
z3/deliverance/sandboxes/paul/dvng/
z3/deliverance/sandboxes/paul/dvng/content3.html
z3/deliverance/sandboxes/paul/dvng/dvngcompiler.py
z3/deliverance/sandboxes/paul/dvng/mycustomizations.xsl
z3/deliverance/sandboxes/paul/dvng/rules.rng
z3/deliverance/sandboxes/paul/dvng/theme.html
z3/deliverance/sandboxes/paul/dvng/theme2.html
z3/deliverance/sandboxes/paul/dvng/themeset.xml
z3/deliverance/sandboxes/paul/dvng/var/
Log:
Making a directory just for the dvng software, instead of the writeup
Added: z3/deliverance/sandboxes/paul/dvng/content3.html
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/content3.html Tue Jun 3 21:01:20 2008
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <title>Red Balloons for Neanderthals</title>
+ <meta name="dv.section" content="DVNG Articles"/>
+ <meta name="dcmi.type" content="Gallery Page"/>
+ <meta name="dcmi.author" content="Grok Smasher"/>
+ <meta name="dcmi.modified" content="2007/02/21"/>
+ </head>
+ <body>
+ <ul id="related">
+ <li><a href="item1">Item One</a></li>
+ <li><a href="item2">Item Two</a></li>
+ </ul>
+ <ul id="breadcrumbs">
+ <li><a href="/">Home</a></li>
+ <li><a href="/articles">Articles</a></li>
+ <li>Red Balloons for Neanderthals</li>
+ </ul>
+ <div id="content">
+ <p>The article text <em>goes here</em>.</p>
+ <p>More content here.</p>
+ </div>
+ </body>
+</html>
Added: z3/deliverance/sandboxes/paul/dvng/dvngcompiler.py
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/dvngcompiler.py Tue Jun 3 21:01:20 2008
@@ -0,0 +1,259 @@
+"""
+Compile a Deliverance themeset into a compiled themeset.
+
+"""
+
+from lxml import etree
+import os
+import sys
+import lxml.html
+
+# Constants
+DV_NAMESPACE = "http://openplans.org/deliverance"
+DV = "{%s}" % DV_NAMESPACE
+XSL_NAMESPACE = "http://www.w3.org/1999/XSL/Transform"
+XSL = "{%s}" % XSL_NAMESPACE
+NSMAP = {"dv": DV_NAMESPACE, "xsl": XSL_NAMESPACE}
+
+
+def dump(node, fn):
+ """Convenience function for quick saving to var directory """
+
+ fullfn = os.path.join("var", fn)
+ f = open(fullfn, "w")
+ f.write(tostring(node))
+ f.close()
+ return
+
+
+def tostring(node):
+ """Convenience function for quick and pretty dumping"""
+
+ return etree.tostring(node, pretty_print=True)
+
+
+def get_tag(node):
+ """Convenience function to get tagname without namespace"""
+
+ return node.tag.split("}")[1]
+
+
+class DVNG2:
+
+ # heredir is set to the directory above step01-04
+ moduledir = os.path.dirname(os.path.abspath(__file__))
+ heredir = os.path.dirname(moduledir)[1:]
+
+ def __init__(self, themesetfn):
+ # Some paths and filenames
+ self.themesetfn = os.path.join(self.moduledir, themesetfn)
+ self.themes = []
+ self.themeset = etree.ElementTree(file=self.themesetfn)
+
+ # The .xsl file that serves as boilerplate for the final
+ stubfn = os.path.join(self.moduledir, "stub.xsl")
+ self.xslt = etree.ElementTree(file=stubfn).getroot()
+
+ def makeThemes(self):
+ """For each theme and page type, make a new Theme"""
+
+ # We support page types by considering each of them
+ # as a distinct theme with a cumulative match condition.
+ # Thus, our XPath matches first on pagetypes and then
+ # on regular themes.
+ pt = self.themeset.xpath("dv:theme/dv:pagetype", namespaces=NSMAP)
+ t = self.themeset.xpath("dv:theme", namespaces=NSMAP)
+
+ i = 0
+ for ptt in pt + t:
+ i = i + 1
+ pttid = get_tag(ptt) + "-" + str(i)
+ theme = Theme(ptt, pttid)
+
+ # Find places in the theme html that need rules inserted
+ # and do so
+ theme.insertRules()
+ theme.makeXSLNode()
+ self.themes.append(theme)
+
+ return
+
+ def assembleStylesheet(self):
+ """Concatenate all the themes into an xsl:stylesheet"""
+
+
+ params = {}
+ xsltemplate = self.xslt.xpath("xsl:template[@match='/']",
+ namespaces=NSMAP)[0]
+ xslchoose = etree.SubElement(xsltemplate, XSL + "choose")
+ for theme in self.themes:
+ # Append the node, then each param
+ xslchoose.append(theme.xslwhen)
+ for param in theme.xslparams.keys():
+ params[param] = True
+
+ # Now generate the param nodes
+ for param in params.keys():
+ node = etree.Element(XSL + "param", name=param)
+ self.xslt.insert(0, node)
+
+ # If there is a /themeset/@custom, use it for custom rules
+ # that need to come in at a higher precedence. Thus,
+ # append them to the end.
+ custom = self.themeset.getroot().get("custom", None)
+ if custom is not None:
+ customfn = os.path.join(self.moduledir, custom)
+ customrules = etree.ElementTree(file=customfn)
+ for rule in customrules.xpath("/*/*"):
+ self.xslt.insert(0, rule)
+
+
+ def debug(self):
+ """Dump the list of themes and the compiled themeset"""
+
+ for theme in self.themes:
+ print "----------\nTheme:", theme.pttid, "at", theme.href
+ print tostring(theme.htmlroot)
+ dump(theme.htmlroot, theme.pttid + "-html.xml")
+ dump(theme.xslwhen, theme.pttid + "-xsl.xml")
+
+ # Now dump the final, assembled XSLT to disk
+ dump(self.xslt, "dvfinalstage.xsl")
+
+ def asString(self):
+ """Serialize the xslt as the string representation"""
+
+ return tostring(self.xslt)
+
+
+class Theme:
+
+ def __init__(self, ptt, pttid):
+ """Given a <pagetype> or a <theme>, make a theme"""
+
+ self.ptt = ptt
+ self.pttid = pttid
+
+ # We are currently sitting on a <pagetype> or a
+ # <theme>. The latter has the @href. Thus,
+ # make an XPath that walks up from the current node
+ # until it finds the @href.
+ self.href = ptt.xpath("ancestor-or-self::*/@href")[0]
+
+ # Load the HTML doc and make a backup copy
+ self.orightmldoc = lxml.html.parse(self.href)
+ self.htmlroot = lxml.html.parse(self.href).getroot()
+
+ # Place to hold <xsl:param> nodes that will go at the
+ # top
+ self.xslparams = {}
+
+ def _getNodes(self, xp):
+ """Convenience function for getting a node by XPath"""
+
+ return self.ptt.xpath(xp, namespaces=NSMAP)
+
+ def insertRules(self):
+ """Find insertion points for rules in the html"""
+
+ rules = self.ptt.xpath("dv:rules", namespaces=NSMAP)[0]
+
+ for rulenode in rules.xpath("*"):
+ targets = self.htmlroot.xpath(rulenode.get("theme"))
+ if not len(targets):
+ # Skip over if nothing in the theme matches
+ continue
+ ruletype = get_tag(rulenode)
+ parent = targets[0].getparent()
+ cxp = rulenode.get("content")
+ makerule = getattr(self, "_rule" + ruletype)
+ makerule(rulenode, parent, targets, cxp)
+
+ def _rulereplace(self, rulenode, parent, targets, cxp):
+
+ newnode = etree.Element(XSL + "apply-templates", select=cxp)
+
+ if len(targets) > 1:
+ # Remove all targets, append xslt to parent
+ [parent.remove(i) for i in targets]
+ parent.append(newnode)
+ # XXX We're not actually getting in here as len()
+ # doesn't do as expected
+ else:
+ parent.replace(targets[0], newnode)
+
+ def matchHandler(self, matchnode):
+ """Given <match> child, return string used in xsl:template"""
+
+ matchtype = get_tag(matchnode)
+ if matchtype == "content":
+ return matchnode.text
+ elif matchtype == "req":
+ pk = matchnode.get("key")
+ pv = matchnode.text
+ # Update the dict that will later drive creation
+ # of /xsl:stylesheet/xsl:param nodes
+ self.xslparams["req." + pk] = True
+
+ # Make the string that will appear in the xsl:template
+ result = "$req.%s='%s'" % (pk, pv)
+ return result
+
+
+ def makeXSLNode(self):
+ """Set the OR'd string of match conditions for this theme"""
+
+ # Make compiler input document by wrapping each theme in
+ # an <xsl:template match="match conditions"
+
+
+ # If we are on a <pagetype>, we need the conditions for
+ # both the pagetype/match and the theme/match. We do this
+ # in two parts, because <pagetype>s need the two sets of
+ # conditions AND'd together.
+ mh = self.matchHandler
+ ptmatches = [mh(m) for m in self._getNodes("dv:match/*")]
+ tmatches = [mh(m) for m in self._getNodes("../dv:match/*")]
+
+ # Handle cases where there are pagetype/match AND theme/match,
+ # just one, or just the other
+ if ptmatches and tmatches:
+ # Make an xsl:template that ANDs both match conditions
+ # for a <pagetype>
+ matchon = "html[%s]" % "(%s) and (%s)" % (
+ " or ".join(ptmatches),
+ " or ".join(tmatches))
+ elif ptmatches:
+ # This is for a <pagetemplate> inside the last
+ # them used when no other themes match
+ matchon = "html[%s]" % " or ".join(ptmatches)
+ elif tmatches:
+ # This is for a theme with either no <pagetype>
+ # or none that match
+ matchon = "html[%s]" % " or ".join(tmatches)
+ else:
+ # Handle the case where we are the last, default theme
+ # that should <xsl:template match="html"> for anything
+ matchon = "html"
+
+ # Now make the actual <xsl:when> node
+ xslnode = XSL + "when"
+ self.xslwhen = etree.Element(xslnode, test=matchon)
+ self.xslwhen.append(self.htmlroot)
+
+
+
+def main():
+ themesetfn = sys.argv[1]
+ dvng = DVNG2(themesetfn)
+ dvng.makeThemes()
+ dvng.assembleStylesheet()
+
+ #dvng.debug()
+
+ result = dvng.asString()
+ return result
+
+if __name__ == "__main__":
+ result = main()
+ print result
Added: z3/deliverance/sandboxes/paul/dvng/mycustomizations.xsl
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/mycustomizations.xsl Tue Jun 3 21:01:20 2008
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template match="/">
+ <div>I overroad everything!</div>
+ </xsl:template>
+</xsl:stylesheet>
Added: z3/deliverance/sandboxes/paul/dvng/rules.rng
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/rules.rng Tue Jun 3 21:01:20 2008
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar
+ xmlns="http://relaxng.org/ns/structure/1.0"
+ xmlns:dv="http://openplans.org/deliverance"
+ xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+ <start>
+ <element name="dv:themeset">
+ <oneOrMore>
+ <element name="dv:theme">
+ <attribute name="href"/>
+ <zeroOrMore>
+ <element name="dv:match">
+ <interleave>
+ <zeroOrMore>
+ <element name="dv:content"><text/></element>
+ </zeroOrMore>
+ <zeroOrMore>
+ <element name="dv:req">
+ <attribute name="key"/>
+ <text/>
+ </element>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </zeroOrMore>
+ <element name="dv:rules">
+ <interleave>
+ <zeroOrMore>
+ <element name="dv:replace">
+ <attribute name="theme"/>
+ <attribute name="content"/>
+ </element>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </element>
+ </oneOrMore>
+ </element>
+ </start>
+</grammar>
\ No newline at end of file
Added: z3/deliverance/sandboxes/paul/dvng/theme.html
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/theme.html Tue Jun 3 21:01:20 2008
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <title>Theme Page Title</title>
+ </head>
+ <body>
+ <h1 id="pageheading">Theme Page Heading</h1>
+ <div id="pagecontent">
+ <p>Some sample theme content.</p>
+ </div>
+ </body>
+</html>
\ No newline at end of file
Added: z3/deliverance/sandboxes/paul/dvng/theme2.html
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/theme2.html Tue Jun 3 21:01:20 2008
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <title>Second Theme Page Title</title>
+ </head>
+ <body>
+ <table border="0" height="300" cellpadding="20">
+ <tr>
+ <td width="200" bgcolor="gray" valign="top">
+ <h2 align="center">Navigation</h2>
+ </td>
+ <td valign="top">
+ <h1 id="pageheading">Theme Page Heading</h1>
+ <div id="pagecontent">Theme content to replace.</div>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
Added: z3/deliverance/sandboxes/paul/dvng/themeset.xml
==============================================================================
--- (empty file)
+++ z3/deliverance/sandboxes/paul/dvng/themeset.xml Tue Jun 3 21:01:20 2008
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<themeset xmlns="http://openplans.org/deliverance" custom="mycustomizations.xsl">
+ <theme href="theme2.html">
+ <pagetype>
+ <match>
+ <content>/html</content>
+ </match>
+ <rules>
+ <replace theme="//td/h1[@id='pageheading']" content="/html/head/title"/>
+ <replace theme="//div[@id='pagecontent']" content="/html/body/div[@id='content']"/>
+ </rules>
+ </pagetype>
+ <match>
+ <!-- These are OR'd together -->
+ <content>/html/head/meta[@name='dv.section']</content>
+ <req key="domain_url">look-at-me.com</req>
+ </match>
+ <rules>
+ <replace theme="//td/h1[@id='pageheading']" content="/html/head/title"/>
+ </rules>
+ </theme>
+ <theme href="theme.html">
+ <rules>
+ <replace theme="//div[@id='pagecontent']" content="/html/body/div[@id='content']"/>
+ </rules>
+ </theme>
+</themeset>
More information about the z3-checkins
mailing list