[z3-checkins] r33191 - in z3/deliverance/branches/packaged/deliverance: . test-data test-data/static
ltucker at codespeak.net
ltucker at codespeak.net
Wed Oct 11 21:54:39 CEST 2006
Author: ltucker
Date: Wed Oct 11 21:54:32 2006
New Revision: 33191
Modified:
z3/deliverance/branches/packaged/deliverance/htmlserialize.py
z3/deliverance/branches/packaged/deliverance/interpreter.py
z3/deliverance/branches/packaged/deliverance/test-data/static/rules.xml
z3/deliverance/branches/packaged/deliverance/test-data/static/text-rules.xml
z3/deliverance/branches/packaged/deliverance/test-data/test_append.xml
z3/deliverance/branches/packaged/deliverance/test-data/test_appendorreplace.xml
z3/deliverance/branches/packaged/deliverance/test-data/test_copy.xml
z3/deliverance/branches/packaged/deliverance/test-data/test_prepend.xml
z3/deliverance/branches/packaged/deliverance/test-data/test_replace.xml
z3/deliverance/branches/packaged/deliverance/utils.py
z3/deliverance/branches/packaged/deliverance/wsgifilter.py
z3/deliverance/branches/packaged/deliverance/xslt.py
Log:
error handling for missing content, fix for foreign character sets
Modified: z3/deliverance/branches/packaged/deliverance/htmlserialize.py
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/htmlserialize.py (original)
+++ z3/deliverance/branches/packaged/deliverance/htmlserialize.py Wed Oct 11 21:54:32 2006
@@ -1,5 +1,5 @@
from lxml import etree
-
+import re
html_xsl = """
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -37,3 +37,26 @@
return str(html_transform(doc))
+
+
+HTTP_EQUIV_MATCHER_PAT = re.compile(r"\<\s*meta\s+([^\>])*http-equiv\s*=\s*(\'|\")\s*content-type\s*(\'|\")([^\>])*charset\s*=\s*(?P<charset>[\w-]+)([^\>])*\>",re.I|re.M)
+OTHER_HTTP_EQUIV_MATCHER_PAT = re.compile(r"\<\s*meta\s+([^\>])*charset\s*=\s*(?P<charset>[\w-]+)([^\>])*http-equiv\s*=\s*(\'|\")\s*content-type\s*(\'|\")([^\>])*\>",re.I|re.M)
+def decodeAndParseHTML(text):
+ """
+ if an html meta tag specifying a charset can be matched,
+ decode the text to a python unicode string before parsing
+ """
+ m = HTTP_EQUIV_MATCHER_PAT.search(text)
+ if not m:
+ m = OTHER_HTTP_EQUIV_MATCHER_PAT.search(text)
+
+ if m:
+ charset = m.group('charset')
+ text = text.decode(charset)
+
+ return etree.HTML(text)
+
+
+
+
+
Modified: z3/deliverance/branches/packaged/deliverance/interpreter.py
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/interpreter.py (original)
+++ z3/deliverance/branches/packaged/deliverance/interpreter.py Wed Oct 11 21:54:32 2006
@@ -62,6 +62,7 @@
content_els = copy.deepcopy(content.xpath(rule.attrib[self.RULE_CONTENT_KEY]))
if (len(content_els) == 0):
+ self.add_to_body_start(theme, self.format_error("no content matched", rule))
return
non_text_els = self.elements_in(content_els)
@@ -96,6 +97,7 @@
content_els = copy.deepcopy(content.xpath(rule.attrib[self.RULE_CONTENT_KEY]))
if (len(content_els) == 0):
+ self.add_to_body_start(theme, self.format_error("no content matched", rule))
return
non_text_els = self.elements_in(content_els)
@@ -141,8 +143,7 @@
content_els = copy.deepcopy(content.xpath(rule.attrib[self.RULE_CONTENT_KEY]))
if len(content_els) == 0:
- self.attach_text_to_previous(theme_el,theme_el.tail)
- theme_el.getparent().remove(theme_el)
+ self.add_to_body_start(theme, self.format_error("no content matched", rule))
return
non_text_els = self.elements_in(content_els)
@@ -195,6 +196,7 @@
content_els = copy.deepcopy(content.xpath(rule.attrib[self.RULE_CONTENT_KEY]))
if len(content_els) == 0:
+ self.add_to_body_start(theme, self.format_error("no content matched", rule))
return
non_text_els = self.elements_in(content_els)
@@ -222,11 +224,16 @@
self.add_to_body_start(theme,self.format_error("invalid xpath for content", rule=rule))
return
+ content_els = copy.deepcopy(content.xpath(content_xpath))
+
+ if len(content_els) == 0:
+ self.add_to_body_start(theme, self.format_error("no content matched", rule))
+ return
+
for el in theme_el:
if el.tag == remove_tag:
theme_el.remove(el)
- content_els = copy.deepcopy(content.xpath(content_xpath))
self.strip_tails(content_els)
theme_el.extend(content_els)
Modified: z3/deliverance/branches/packaged/deliverance/test-data/static/rules.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/static/rules.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/static/rules.xml Wed Oct 11 21:54:32 2006
@@ -2,8 +2,8 @@
<rules xmlns="http://www.plone.org/deliverance">
<append-or-replace theme="//head" content="//head/title" />
<append theme="//head" content="//head/link" />
- <append theme="//head" content="//head/script" />
- <append theme="//head" content="//head/style" />
- <append theme="//head" content="//head/meta" />
+ <append theme="//head" content="//head/script" onerror="ignore" />
+ <append theme="//head" content="//head/style" onerror="ignore" />
+ <append theme="//head" content="//head/meta" onerror="ignore" />
<copy theme="//div[@id='content']" content="//body/*" />
</rules>
Modified: z3/deliverance/branches/packaged/deliverance/test-data/static/text-rules.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/static/text-rules.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/static/text-rules.xml Wed Oct 11 21:54:32 2006
@@ -2,8 +2,8 @@
<rules xmlns="http://www.plone.org/deliverance">
<append-or-replace theme="//head" content="//head/title" />
<append theme="//head" content="//head/link" />
- <append theme="//head" content="//head/script" />
- <append theme="//head" content="//head/style" />
- <append theme="//head" content="//head/meta" />
+ <append theme="//head" content="//head/script" onerror="ignore"/>
+ <append theme="//head" content="//head/style" onerror="ignore"/>
+ <append theme="//head" content="//head/meta" onerror="ignore"/>
<copy theme="//div[@id='content']" content="//body/child::node()" />
</rules>
Modified: z3/deliverance/branches/packaged/deliverance/test-data/test_append.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/test_append.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/test_append.xml Wed Oct 11 21:54:32 2006
@@ -68,17 +68,51 @@
</content>
<output>
- <html>
- <head>
- <title>Blah</title>
- </head>
- <body>
- <div class="foo">Dummy Content<div class="deliverance-error">
- Deliverance error: multiple elements found in theme<br/>rule: <append theme=".//div[@class='foo']" content=".//div[@id='bar']"/>
- </div></div>
- <div class="foo">Dummy Content</div>
- </body>
- </html>
+ <html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <append theme=".//div[@class='foo']" content=".//div[@id='bar']"/>
+ <br/><textarea rows="24" cols="80" readonly="readonly"><div class="foo">Dummy Content</div>
+<div class="foo">Dummy Content</div>
+</textarea></div>
+ <div class="foo">Dummy Content</div>
+ <div class="foo">Dummy Content</div>
+ </body>
+</html>
+
+ </output>
+</deliverance-test>
+
+
+<!-- tests append command generates an error when no content is found -->
+<deliverance-test>
+ <rules xmlns="http://www.plone.org/deliverance">
+ <append theme=".//div[@id='foo']" content="//div[@id='bar']" />
+ </rules>
+
+ <theme base="http://example.com">
+ <html><head><title>Blah</title></head><body><div></div><div id="foo">Dummy Content<p>HI!</p></div>
+ </body></html>
+ </theme>
+
+ <content>
+ <html><body>leading text <br/> more <p>inside p </p>trailing text</body> tail of body</html>
+ </content>
+
+ <output>
+<html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: no content matched<br/>rule: <append theme=".//div[@id='foo']" content="//div[@id='bar']"/>
+ </div>
+ <div/>
+ <div id="foo">Dummy Content<p>HI!</p></div>
+ </body>
+</html>
</output>
</deliverance-test>
Modified: z3/deliverance/branches/packaged/deliverance/test-data/test_appendorreplace.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/test_appendorreplace.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/test_appendorreplace.xml Wed Oct 11 21:54:32 2006
@@ -91,18 +91,20 @@
</content>
<output>
- <html>
- <head>
- <title>Blah</title>
- </head>
- <body>
- <div>Dummy Content<div class="deliverance-error">
- Deliverance error: multiple elements found in theme<br/>rule: <append-or-replace theme=".//div" content=".//div"/>
- </div></div>
- <div>Dummy Content</div>
- </body>
- </html>
- </output>
+ <html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <append-or-replace theme=".//div" content=".//div"/>
+ <br/><textarea rows="24" cols="80" readonly="readonly"><div>Dummy Content</div>
+<div>Dummy Content</div>
+ </textarea></div>
+ <div>Dummy Content</div>
+ <div>Dummy Content</div>
+ </body>
+ </html>
+ </output>
</deliverance-test>
@@ -167,4 +169,38 @@
</output>
</deliverance-test>
+
+
+
+<!-- tests append-or-replace command generates an error when no content is found -->
+<deliverance-test>
+ <rules xmlns="http://www.plone.org/deliverance">
+ <append-or-replace theme=".//div[@id='foo']" content="//span[@id='bar']" />
+ </rules>
+
+ <theme base="http://example.com">
+ <html><head><title>Blah</title></head><body><div></div><div id="foo"><span>Dummy Content</span><p>HI!</p></div>
+ </body></html>
+ </theme>
+
+ <content>
+ <html><body>leading text <br/> more <p>inside p </p>trailing text</body> tail of body</html>
+ </content>
+
+ <output>
+<html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: no content matched<br/>rule: <append-or-replace theme=".//div[@id='foo']" content="//span[@id='bar']"/>
+ </div>
+ <div/>
+ <div id="foo"><span>Dummy Content</span><p>HI!</p></div>
+ </body>
+</html>
+ </output>
+</deliverance-test>
+
</deliverance-test-suite>
+
Modified: z3/deliverance/branches/packaged/deliverance/test-data/test_copy.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/test_copy.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/test_copy.xml Wed Oct 11 21:54:32 2006
@@ -69,11 +69,15 @@
<title>Blah</title>
</head>
<body>
- <div class="foo">Dummy Content<div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <copy theme=".//div[@class='foo']" content=".//div[@id='bar']"/>
- </div></div>
+ <div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <copy theme=".//div[@class='foo']" content=".//div[@id='bar']"/>
+ <br/><textarea rows="24" cols="80" readonly="readonly"><div class="foo">Dummy Content</div>
+<div class="foo">Dummy Content</div>
+</textarea></div>
+ <div class="foo">Dummy Content</div>
<div class="foo">Dummy Content</div>
</body>
</html>
+
</output>
</deliverance-test>
@@ -120,4 +124,35 @@
</deliverance-test>
+<!-- tests copy command generates an error when no content is found -->
+<deliverance-test>
+ <rules xmlns="http://www.plone.org/deliverance">
+ <copy theme=".//div[@id='foo']" content="//div[@id='bar']" />
+ </rules>
+
+ <theme base="http://example.com">
+ <html><head><title>Blah</title></head><body><div></div><div id="foo">Dummy Content<p>HI!</p></div>
+ </body></html>
+ </theme>
+
+ <content>
+ <html><body>leading text <br/> more <p>inside p </p>trailing text</body> tail of body</html>
+ </content>
+
+ <output>
+<html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: no content matched<br/>rule: <copy theme=".//div[@id='foo']" content="//div[@id='bar']"/>
+ </div>
+ <div/>
+ <div id="foo">Dummy Content<p>HI!</p></div>
+ </body>
+</html>
+ </output>
+</deliverance-test>
+
+
</deliverance-test-suite>
Modified: z3/deliverance/branches/packaged/deliverance/test-data/test_prepend.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/test_prepend.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/test_prepend.xml Wed Oct 11 21:54:32 2006
@@ -68,22 +68,25 @@
</content>
<output>
- <html>
- <head>
- <title>Blah</title>
- </head>
- <body>
- <div class="foo">Dummy Content<div class="deliverance-error">
- Deliverance error: multiple elements found in theme<br/>rule: <prepend theme=".//div[@class='foo']" content=".//div[@id='bar']"/>
- </div></div>
- <div class="foo">Dummy Content</div>
- </body>
- </html>
+<html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <prepend theme=".//div[@class='foo']" content=".//div[@id='bar']"/>
+ <br/><textarea rows="24" cols="80" readonly="readonly"><div class="foo">Dummy Content</div>
+<div class="foo">Dummy Content</div>
+</textarea></div>
+ <div class="foo">Dummy Content</div>
+ <div class="foo">Dummy Content</div>
+ </body>
+</html>
+
</output>
</deliverance-test>
-<!-- tests preppend command successfully prepends the contents of a div tag with all contents of body tag,
+<!-- tests prepend command successfully prepends the contents of a div tag with all contents of body tag,
including unelemented text -->
<deliverance-test>
<rules xmlns="http://www.plone.org/deliverance">
@@ -105,4 +108,35 @@
</output>
</deliverance-test>
+
+<!-- tests prepend command generates an error when no content is found -->
+<deliverance-test>
+ <rules xmlns="http://www.plone.org/deliverance">
+ <prepend theme=".//div[@id='foo']" content="//div[@id='bar']" />
+ </rules>
+
+ <theme base="http://example.com">
+ <html><head><title>Blah</title></head><body><div></div><div id="foo">Dummy Content<p>HI!</p></div>
+ </body></html>
+ </theme>
+
+ <content>
+ <html><body>leading text <br/> more <p>inside p </p>trailing text</body> tail of body</html>
+ </content>
+
+ <output>
+<html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: no content matched<br/>rule: <prepend theme=".//div[@id='foo']" content="//div[@id='bar']"/>
+ </div>
+ <div/>
+ <div id="foo">Dummy Content<p>HI!</p></div>
+ </body>
+</html>
+ </output>
+</deliverance-test>
+
</deliverance-test-suite>
Modified: z3/deliverance/branches/packaged/deliverance/test-data/test_replace.xml
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/test-data/test_replace.xml (original)
+++ z3/deliverance/branches/packaged/deliverance/test-data/test_replace.xml Wed Oct 11 21:54:32 2006
@@ -76,16 +76,20 @@
</content>
<output>
- <html>
- <head>
+<html>
+ <head>
<title>Blah</title>
</head>
<body>
- <div class="foo">Dummy Content<div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <replace theme="//div[@class='foo']" content="//div[@id='bar']"/>
- </div></div>
+ <div class="deliverance-error">Deliverance error: multiple elements found in theme<br/>rule: <replace theme="//div[@class='foo']" content="//div[@id='bar']"/>
+ <br/><textarea rows="24" cols="80" readonly="readonly"><div class="foo">Dummy Content</div>
+<div class="foo">Dummy Content</div>
+</textarea></div>
+ <div class="foo">Dummy Content</div>
<div class="foo">Dummy Content</div>
</body>
</html>
+
</output>
</deliverance-test>
@@ -148,22 +152,34 @@
</output>
</deliverance-test>
-<!-- tests that when no content element is matched, the theme element is simply deleted without error -->
+
+<!-- tests replace command generates an error when no content is found -->
<deliverance-test>
<rules xmlns="http://www.plone.org/deliverance">
- <replace theme="//div[@id='foo']" content="//div[@id='bar']" />
+ <replace theme=".//div[@id='foo']" content="//div[@id='bar']" />
</rules>
<theme base="http://example.com">
- <html><head><title>Blah</title></head><body>lead<div id="foo">Dummy Content</div>tail</body></html>
+ <html><head><title>Blah</title></head><body><div></div><div id="foo">Dummy Content<p>HI!</p></div>
+ </body></html>
</theme>
<content>
- <html><body><div id="bars">Real Content</div></body></html>
+ <html><body>leading text <br/> more <p>inside p </p>trailing text</body> tail of body</html>
</content>
-
+
<output>
- <html><head><title>Blah</title></head><body>leadtail</body></html>
+<html>
+ <head>
+ <title>Blah</title>
+ </head>
+ <body>
+ <div class="deliverance-error">Deliverance error: no content matched<br/>rule: <replace theme=".//div[@id='foo']" content="//div[@id='bar']"/>
+ </div>
+ <div/>
+ <div id="foo">Dummy Content<p>HI!</p></div>
+ </body>
+</html>
</output>
</deliverance-test>
Modified: z3/deliverance/branches/packaged/deliverance/utils.py
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/utils.py (original)
+++ z3/deliverance/branches/packaged/deliverance/utils.py Wed Oct 11 21:54:32 2006
@@ -1,6 +1,7 @@
from lxml import etree
import re
import urlparse
+import htmlserialize
class RuleSyntaxError(Exception):
"""
@@ -38,8 +39,8 @@
self.add_to_body_start(theme, e)
return None
elif len(theme_els)> 1:
- e = self.format_error("multiple elements found in theme", rule)
- theme_els[0].append(e)
+ e = self.format_error("multiple elements found in theme", rule, theme_els)
+ self.add_to_body_start(theme, e)
return None
return theme_els[0]
@@ -61,7 +62,15 @@
br.tail = 'rule: %s' % etree.tostring(rule)
d.append(br)
if elts:
- d.extend(elts)
+ d.append(etree.Element('br'))
+ textArea = etree.Element('textarea')
+ textArea.attrib['rows'] = '24'
+ textArea.attrib['cols'] = '80'
+ textArea.attrib['readonly'] = 'readonly'
+ textArea.text = ''
+ for el in elts:
+ textArea.text += htmlserialize.tostring(el)
+ d.append(textArea)
return d
@@ -75,6 +84,8 @@
def add_to_body_start(self,theme, el):
+ if not el:
+ return
body = theme.find('body')
if body is None:
body = theme[0]
Modified: z3/deliverance/branches/packaged/deliverance/wsgifilter.py
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/wsgifilter.py (original)
+++ z3/deliverance/branches/packaged/deliverance/wsgifilter.py Wed Oct 11 21:54:32 2006
@@ -8,6 +8,8 @@
import urlparse
import urllib
from lxml import etree
+#from lxml.etree import HTML as parseHTML
+from htmlserialize import decodeAndParseHTML as parseHTML
from paste.wsgilib import intercept_output
from paste.request import construct_url
from paste.response import header_value, replace_header
@@ -36,7 +38,6 @@
try:
self._lock.acquire()
if not self._renderer or self.cache_expired():
- print "rebuild renderer"
self._renderer = self.create_renderer(environ)
self._cache_time = datetime.datetime.now()
return self._renderer
@@ -57,7 +58,7 @@
elif encoding:
return text.decode(encoding)
- return Renderer(etree.HTML(theme), full_theme_uri, etree.XML(rule),
+ return Renderer(parseHTML(theme), full_theme_uri, etree.XML(rule),
reference_resolver=reference_resolver)
@@ -86,6 +87,7 @@
if status is None:
# should_intercept returned False
return body
+
body = self.filter_body(environ, body)
replace_header(headers, 'content-length', str(len(body)))
replace_header(headers, 'content-type', 'text/html; charset=utf-8')
@@ -97,8 +99,8 @@
return type.startswith('text/html') or type.startswith('application/xhtml+xml')
def filter_body(self, environ, body):
- content = self.get_renderer(environ).render(etree.HTML(body))
- return tostring(content)
+ content = self.get_renderer(environ).render(parseHTML(body))
+ return tostring(content)
def get_resource(self, environ, uri):
internalBaseURL = environ.get(DELIVERANCE_BASE_URL,None)
Modified: z3/deliverance/branches/packaged/deliverance/xslt.py
==============================================================================
--- z3/deliverance/branches/packaged/deliverance/xslt.py (original)
+++ z3/deliverance/branches/packaged/deliverance/xslt.py Wed Oct 11 21:54:32 2006
@@ -42,7 +42,9 @@
insertion_point = xslt_wrapper.xpath("//xsl:transform/xsl:template[@match='/']",
nsmap)[0]
insertion_point.append(theme_copy)
+
self.transform = etree.XSLT(xslt_wrapper)
+
def render(self,content):
@@ -81,15 +83,24 @@
if theme_el is None:
return
+ # add an element that produces an error in the theme if
+ # no content is matched
+ self.add_conditional_missing_content_error(theme,rule)
+
copier = etree.SubElement(theme_el,
"{%s}copy-of" % nsmap["xsl"])
copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
+
def apply_prepend(self,rule,theme):
theme_el = self.get_theme_el(rule,theme)
if theme_el is None:
return
+ # add an element that produces an error in the theme if
+ # no content is matched
+ self.add_conditional_missing_content_error(theme,rule)
+
copier = etree.Element("{%s}copy-of" % nsmap["xsl"])
copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
@@ -102,11 +113,21 @@
theme_el = self.get_theme_el(rule,theme)
if theme_el is None:
return
-
+
+ self.add_conditional_missing_content_error(theme,rule)
+
copier = etree.Element("{%s}copy-of" % nsmap["xsl"])
copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
- self.replace_element(theme_el,copier)
+
+ # if content is matched, replace the theme element, otherwise, keep the
+ # theme element
+ choose = self.make_when_otherwise("count(%s)=0" %
+ rule.attrib[self.RULE_CONTENT_KEY],
+ copy.deepcopy(theme_el),
+ copier)
+
+ self.replace_element(theme_el,choose)
def apply_copy(self,rule,theme):
@@ -114,11 +135,30 @@
if theme_el is None:
return
- del(theme_el[:])
- theme_el.text = None
+ # add an element that produces an error in the theme if
+ # no content is matched
+ self.add_conditional_missing_content_error(theme,rule)
+
+ # create an element that is like the target theme element
+ # with its children replaced by an xsl copy element
+ copy_theme_el = copy.deepcopy(theme_el)
+ del(copy_theme_el[:])
+ copy_theme_el.text = None
copier = etree.SubElement(theme_el,
"{%s}copy-of" % nsmap["xsl"])
- copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
+ copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
+ copy_theme_el.append(copier)
+
+ # create a copy of the current theme element
+ normal_theme_el = copy.deepcopy(theme_el)
+
+ # create an xsl choose element that picks between them based
+ # on whether content was matched
+ choose = self.make_when_otherwise("count(%s)=0" %
+ rule.attrib[self.RULE_CONTENT_KEY],
+ normal_theme_el,
+ copy_theme_el)
+ self.replace_element(theme_el,choose)
@@ -131,12 +171,21 @@
self.add_to_body_start(theme,self.format_error("invalid xpath for content", rule=rule))
return
+ # add an element that produces an error in the theme if
+ # no content is matched
+ self.add_conditional_missing_content_error(theme,rule)
+
for el in theme_el:
if el.tag == remove_tag:
- theme_el.remove(el)
- copier = etree.SubElement(theme_el,
- "{%s}copy-of" % nsmap["xsl"])
- copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
+ conditional = etree.Element("{%s}if" % nsmap["xsl"])
+ conditional.set("test","count(%s) = 0" %
+ rule.attrib[self.RULE_CONTENT_KEY])
+ conditional.append(copy.deepcopy(el))
+ self.replace_element(el,conditional)
+
+ copier = etree.Element("{%s}copy-of" % nsmap["xsl"])
+ copier.set("select",rule.attrib[self.RULE_CONTENT_KEY])
+ theme_el.append(copier)
def xsl_escape_comments(self,doc):
@@ -149,3 +198,24 @@
escaped.text = c.text
self.replace_element(c,escaped)
+ def add_conditional_missing_content_error(self,theme,rule):
+ """
+ """
+ err = self.format_error("no content matched", rule)
+ if err:
+ conditional = etree.Element("{%s}if" % nsmap["xsl"])
+ conditional.set("test", "count(%s)=0" % rule.attrib[self.RULE_CONTENT_KEY])
+ conditional.append(err)
+ self.add_to_body_start(theme,conditional)
+
+
+ def make_when_otherwise(self, test, whenbody, otherwisebody):
+ choose = etree.Element("{%s}choose" % nsmap["xsl"])
+ when = etree.Element("{%s}when" % nsmap["xsl"])
+ when.set("test", test)
+ when.append(copy.deepcopy(whenbody))
+ otherwise = etree.Element("{%s}otherwise" % nsmap["xsl"])
+ otherwise.append(otherwisebody)
+ choose.append(when)
+ choose.append(otherwise)
+ return choose
More information about the z3-checkins
mailing list