[4suite-checkins] In 4Suite/Ft/Xml/Xslt,
files ApplyTemplatesElement.py, CallTemplateElement.py,
ChooseElement.py, ContentInfo.py, ForEachElement.py,
GenericVariable.py, LiteralElement.py, Processor.py,
Stylesheet.py, StylesheetHandler.py, StylesheetReader.py,
StylesheetTree.py, TemplateElement.py, TextElement.py,
UndefinedElements.py, ValueOfElement.py, XPathExtensions.py,
XsltContext.py, XsltFunctions.py
Jeremy Kloth
jkloth at 4suite.org
Mon Nov 27 09:29:30 MST 2006
- Previous message: [4suite-checkins] In 4Suite/Ft/Xml/XPath, files MessageSource.py,
ParsedExpr.py
- Next message: [4suite-checkins]
In 4Suite/Ft/Xml/Xslt/src, files stylesheet_tree.c,
xsltelement.c, xsltelement.h, xsltnode.c, xsltnode.h,
xsltroot.c, xsltroot.h, xslttext.c, xslttext.h
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Modified Files:
ApplyTemplatesElement.py CallTemplateElement.py ChooseElement.py
ContentInfo.py ForEachElement.py GenericVariable.py
LiteralElement.py Processor.py Stylesheet.py StylesheetHandler.py
StylesheetReader.py StylesheetTree.py TemplateElement.py
TextElement.py UndefinedElements.py ValueOfElement.py
XPathExtensions.py XsltContext.py XsltFunctions.py
Log Message:
- Xslt{Node,Root,Text,Element} are now C-types; this reduces memory footprint
add paves the way for a C-based StylesheetReader.
- ContentInfo classes replace by Domlette's ContentModel; this should be
transparent to implementors
- StylesheetHandler streamlined; only visible change is now CategoryTypes
(i.e., .category on XsltElement subclasses) is ignored for validation
purposes.
- Miscellaneous other speedups
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ApplyTemplatesElement.py.diff?r1=1.10&r2=1.11
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ApplyTemplatesElement.py?rev=1.11&content-type=text/vnd.viewcvs-markup
Index: ApplyTemplatesElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/ApplyTemplatesElement.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -U2 -r1.10 -r1.11
--- ApplyTemplatesElement.py 6 Apr 2005 23:05:47 -0000 1.10
+++ ApplyTemplatesElement.py 27 Nov 2006 16:29:29 -0000 1.11
@@ -26,5 +26,5 @@
}
- doesSetup = 1
+ doesSetup = True
def setup(self):
@@ -68,6 +68,5 @@
# Iterate over the nodes
- state = context.copy()
- mode = context.mode
+ state = context.node, context.position, context.size, context.mode
context.mode = self._instantiate_mode(context)
@@ -78,6 +77,4 @@
processor.applyTemplates(context, with_params)
pos += 1
-
- context.mode = mode
- context.set(state)
+ context.node, context.position, context.size, context.mode = state
return
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/CallTemplateElement.py.diff?r1=1.11&r2=1.12
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/CallTemplateElement.py?rev=1.12&content-type=text/vnd.viewcvs-markup
Index: CallTemplateElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/CallTemplateElement.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -U2 -r1.11 -r1.12
--- CallTemplateElement.py 6 Apr 2005 23:05:47 -0000 1.11
+++ CallTemplateElement.py 27 Nov 2006 16:29:29 -0000 1.12
@@ -31,9 +31,8 @@
self._tail_recursive = 0
self._called_template = None
- self._params = map(lambda with_param:
- (with_param, with_param._name, with_param._select),
- self.children)
+ self._params = [ (child, child._name, child._select.evaluate)
+ for child in self.children ]
return
-
+
def prime(self, processor, context):
self._called_template = processor._namedTemplates.get(self._name)
@@ -51,7 +50,7 @@
while node is not current:
if not (node.isLastChild() and \
- (node.expandedName[0] == XSL_NAMESPACE and
- node.expandedName[1] in ['choose', 'if',
- 'otherwise', 'when'])
+ (node.expandedName[0] == XSL_NAMESPACE and
+ node.expandedName[1] in ('choose', 'if',
+ 'otherwise', 'when'))
):
use_tail = 0
@@ -81,5 +80,5 @@
context.processorNss = param.namespaces
context.currentInstruction = param
- params[name] = expr.evaluate(context)
+ params[name] = expr(context)
if self._tail_recursive:
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ChooseElement.py.diff?r1=1.4&r2=1.5
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ChooseElement.py?rev=1.5&content-type=text/vnd.viewcvs-markup
Index: ChooseElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/ChooseElement.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -U2 -r1.4 -r1.5
--- ChooseElement.py 6 Apr 2005 23:05:47 -0000 1.4
+++ ChooseElement.py 27 Nov 2006 16:29:29 -0000 1.5
@@ -46,19 +46,25 @@
if not self.children:
raise XsltException(Error.CHOOSE_REQUIRES_WHEN)
+ elif isinstance(self.children[-1], OtherwiseElement):
+ self._choices = self.children[:-1]
+ self._otherwise = self.children[-1]
+ else:
+ self._choices = self.children
+ self._otherwise = None
+ self._choices = [ (child, child._test.evaluate)
+ for child in self._choices ]
return
def instantiate(self, context, processor):
- chosen = None
- for child in self.children:
+ for child, test in self._choices:
context.processorNss = child.namespaces
context.currentInstruction = child
- if isinstance(child, WhenElement):
- if Conversions.BooleanValue(child._test.evaluate(context)):
- chosen = child
- break
- else:
- # xsl:otherwise
+ if Conversions.BooleanValue(test(context)):
chosen = child
+ break
+ else:
+ # xsl:otherwise
+ chosen = self._otherwise
if chosen:
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ContentInfo.py.diff?r1=1.8&r2=1.9
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ContentInfo.py?rev=1.9&content-type=text/vnd.viewcvs-markup
Index: ContentInfo.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/ContentInfo.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -U2 -r1.8 -r1.9
--- ContentInfo.py 16 Jan 2005 07:34:39 -0000 1.8
+++ ContentInfo.py 27 Nov 2006 16:29:29 -0000 1.9
@@ -1,234 +1,132 @@
-import sys
+from Ft.Xml.cDomlettec import ContentModel
+from Ft.Xml.Lib.XmlString import IsQName
from Ft.Xml.Xslt import XSL_NAMESPACE
-from Ft.Xml.Xslt import CategoryTypes
-TEXT_NODE = (None, None)
-EMPTY = -sys.maxint
-ELSE = EMPTY + 1
+__all__ = ['QName', 'Seq', 'Alt', 'Rep1', 'Rep', 'Opt',
+ 'Empty', 'Text', 'ResultElements', 'Instructions', 'Template',
+ 'TopLevelElements',
+ ]
-class Atom:
+RESULT_ELEMENT = (None, None)
+TEXT_NODE = '#PCDATA'
+EMPTY = '/empty/'
+END_ELEMENT = ContentModel.FINAL_EVENT
+
+def QName(namespaceUri, qualifiedName):
"""
- Atom(arg)
- matches exactly one occurence of 'arg'
+ Matches a fully qualified name (e.g., xsl:sort)
"""
- def __init__(self, token):
- self.token = token
+ assert IsQName(qualifiedName)
+ if ':' in qualifiedName:
+ localName = qualifiedName[qualifiedName.index(':')+1:]
+ else:
+ localName = qualifiedName
+ return ContentModel(ContentModel.TYPE_NAME, (namespaceUri, localName),
+ label=qualifiedName)
- def buildValidator(self, validator, initial, final):
- validator.transition(self.token, initial, final)
- return
-
-class Seq:
+def Seq(*args):
"""
- Seq(arg1, arg2, arg3...)
- matches arg1 followed by arg2 followed by arg3...
+ Matches the each argument in sequential order.
"""
- def __init__(self, *args):
- self.args = []
- for arg in args:
- if isinstance(arg, type('')):
- arg = QName(arg)
- self.args.append(arg)
- return
-
- def __str__(self):
- if len(self.args) > 1:
- return '(%s)' % ', '.join(map(str, self.args))
- else:
- return str(self.args[0])
-
- def buildValidator(self, validator, initial, final):
- s1 = initial
- for arg in self.args[:-1]:
- s2 = {}
- arg.buildValidator(validator, s1, s2)
- s1 = s2
- self.args[-1].buildValidator(validator, s1, final)
- return
+ return ContentModel(ContentModel.TYPE_SEQ, args)
-class Alt:
+def Alt(*args):
"""
- Alt(arg1, arg2, arg3...)
- matches arg1 or arg2 or arg3...
+ Matches one of the given arguments.
"""
-
- def __init__(self, *args):
- self.args = []
- for arg in args:
- if isinstance(arg, type('')):
- arg = QName(arg)
- self.args.append(arg)
- return
-
- def __str__(self):
- if len(self.args) > 1:
- return '(%s)' % ' | '.join(map(str, self.args))
- else:
- return str(self.args[0])
-
- def buildValidator(self, validator, initial, final):
- for arg in self.args:
- arg.buildValidator(validator, initial, final)
- return
+ return ContentModel(ContentModel.TYPE_ALT, args)
-class Rep1:
+def Rep1(arg):
"""
- Rep1(arg)
- matches one or more occurrences of 'arg'
+ Matches one or more occurrences of 'arg'.
"""
- def __init__(self, arg):
- if isinstance(arg, type('')):
- arg = QName(arg)
- self.arg = arg
- return
+ assert isinstance(arg, ContentModel)
+ arg.quant = ContentModel.QUANT_PLUS
+ return arg
- def __str__(self):
- return '%s+' % str(self.arg)
- def buildValidator(self, validator, initial, final):
- state = {}
- self.arg.buildValidator(validator, initial, state)
- self.arg.buildValidator(validator, state, state)
- validator.transition(ELSE, state, final)
- return
-
-class Opt:
+def Opt(arg):
"""
- Opt(arg)
- matches zero or one occurrences of 'arg'
+ Matches zero or one occurrences of 'arg'
"""
+ assert isinstance(arg, ContentModel)
+ arg.quant = ContentModel.QUANT_OPT
+ return arg
- def __init__(self, arg):
- if isinstance(arg, type('')):
- arg = QName(arg)
- self.arg = arg
- return
-
- def __str__(self):
- return '%s?' % str(self.arg)
-
- def buildValidator(self, validator, initial, final):
- self.arg.buildValidator(validator, initial, final)
- return
-class Rep:
+def Rep(arg):
"""
- Rep(arg)
- matches zero or more occurrences of 'arg'
+ Matches zero or more occurrences of 'arg'
"""
- def __init__(self, arg):
- if isinstance(arg, type('')):
- arg = QName(arg)
- self.arg = arg
- return
-
- def __str__(self):
- return '%s*' % str(self.arg)
-
- def buildValidator(self, validator, initial, final):
- self.arg.buildValidator(validator, initial, initial)
- validator.transition(ELSE, initial, final)
- return
+ assert isinstance(arg, ContentModel)
+ arg.quant = ContentModel.QUANT_REP
+ return arg
# special match that matches nothing
-Empty = Atom(EMPTY)
-Empty.__str__ = lambda : '/empty/'
-Empty.__doc__ = """
-Empty is the content model for childless elements
-"""
-Empty.__nonzero__ = lambda : 0
-
-Text = Atom(TEXT_NODE)
-Text.__str__ = lambda : '#PCDATA'
-Text.__doc__ = """\
-Text is any PCDATA content
-"""
-
-class QName(Atom):
- """
- QName(namespaceUri, qualifiedName)
- matches a fully qualified name (e.g., xsl:sort)
- """
- def __init__(self, namespaceUri, qualifiedName):
- self.qualifiedName = qualifiedName
- index = qualifiedName.rfind(':')
- if index == -1:
- local = qualifiedName
- else:
- local = qualifiedName[index+1:]
- Atom.__init__(self, (namespaceUri, local))
- return
-
- def __str__(self):
- return self.qualifiedName
-
-
-ResultElements = Rep(Atom(CategoryTypes.RESULT_ELEMENT))
-ResultElements.__str__ = lambda : '/result-elements/'
-ResultElements.__doc__ = """
-ResultElements is the set of elements not declared in the XSL namespace
-"""
-
-Instructions = Rep(Atom(CategoryTypes.INSTRUCTION))
-Instructions.__str__ = lambda : '/instructions/'
-Instructions.__doc__ = """\
-Instructions is the set of elements which have a category of instruction
-"""
-
-Template = Rep(Alt(Text,
- QName(XSL_NAMESPACE, 'xsl:variable'),
- Atom(CategoryTypes.INSTRUCTION),
- Atom(CategoryTypes.RESULT_ELEMENT)))
-Template.__str__ = lambda : '/template/'
-Template.__doc__ = """
-Template is the set of text, instructions or result-elements
-"""
-
-TopLevelElements = Rep(Alt(QName(XSL_NAMESPACE, 'xsl:variable'),
- QName(XSL_NAMESPACE, 'xsl:param'),
- Atom(CategoryTypes.TOP_LEVEL_ELEMENT),
- Atom(CategoryTypes.RESULT_ELEMENT)))
-TopLevelElements.__str__ = lambda : '/top-level-elements/'
-TopLevelElements.__doc__ = """\
-TopLevelElements is the set of elements which have a category of
-top-level-element or are a result-element.
-"""
-
-class Validator:
- def __init__(self, expr):
- if expr is None:
- expr = Empty
- self._expr = expr
- self._initial = {}
- expr.buildValidator(self, self._initial, {})
- return
-
- def __str__(self):
- return str(self._expr)
-
- def transition(self, token, state1, state2):
- state = state1.get(token)
- if not state:
- # this is the first one
- state1[token] = state2
- else:
- # make new epsilon state
- new_state = {}
- state1[token] = new_state
- new_state[token] = state
- new_state[ELSE] = state2
- return
-
- def getValidation(self):
- return self._initial
-
- def validate(self, validation, token):
- new_state = validation.get(token, -1)
- if new_state == -1 and validation.has_key(ELSE):
- new_state = validation[ELSE].get(token)
- return new_state
-
+Empty = ContentModel(ContentModel.TYPE_NAME, EMPTY, ContentModel.QUANT_OPT,
+ label='/empty/',
+ doc="Empty is the content model for childless elements")
+
+Text = ContentModel(ContentModel.TYPE_NAME, TEXT_NODE,
+ ContentModel.QUANT_REP,
+ label="#PCDATA",
+ doc="Text is the content model for text content")
+
+ResultElements = ContentModel(ContentModel.TYPE_NAME, RESULT_ELEMENT,
+ ContentModel.QUANT_REP,
+ label='/result-elements/',
+ doc=("ResultElements is the set of elements not"
+ " declared in the XSL namespace"))
+
+Instructions = (QName(XSL_NAMESPACE, 'xsl:apply-templates'),
+ QName(XSL_NAMESPACE, 'xsl:call-template'),
+ QName(XSL_NAMESPACE, 'xsl:apply-imports'),
+ QName(XSL_NAMESPACE, 'xsl:for-each'),
+ QName(XSL_NAMESPACE, 'xsl:value-of'),
+ QName(XSL_NAMESPACE, 'xsl:copy-of'),
+ QName(XSL_NAMESPACE, 'xsl:number'),
+ QName(XSL_NAMESPACE, 'xsl:choose'),
+ QName(XSL_NAMESPACE, 'xsl:if'),
+ QName(XSL_NAMESPACE, 'xsl:text'),
+ QName(XSL_NAMESPACE, 'xsl:copy'),
+ QName(XSL_NAMESPACE, 'xsl:variable'),
+ QName(XSL_NAMESPACE, 'xsl:message'),
+ QName(XSL_NAMESPACE, 'xsl:fallback'),
+ QName(XSL_NAMESPACE, 'xsl:processing-instruction'),
+ QName(XSL_NAMESPACE, 'xsl:comment'),
+ QName(XSL_NAMESPACE, 'xsl:element'),
+ QName(XSL_NAMESPACE, 'xsl:attribute'))
+Instructions = ContentModel(ContentModel.TYPE_ALT, Instructions,
+ ContentModel.QUANT_REP, label='/instructions/',
+ doc=("Instructions is the set of elements which"
+ " have a category of instruction"))
+
+Template = ContentModel(ContentModel.TYPE_ALT,
+ (Text, Instructions, ResultElements),
+ ContentModel.QUANT_REP, label='/template/',
+ doc=("Template is the set of text, instructions"
+ " or result-elements"))
+
+TopLevelElements = (QName(XSL_NAMESPACE, 'xsl:include'),
+ QName(XSL_NAMESPACE, 'xsl:strip-space'),
+ QName(XSL_NAMESPACE, 'xsl:preserve-space'),
+ QName(XSL_NAMESPACE, 'xsl:output'),
+ QName(XSL_NAMESPACE, 'xsl:key'),
+ QName(XSL_NAMESPACE, 'xsl:decimal-format'),
+ QName(XSL_NAMESPACE, 'xsl:attribute-set'),
+ QName(XSL_NAMESPACE, 'xsl:variable'),
+ QName(XSL_NAMESPACE, 'xsl:param'),
+ QName(XSL_NAMESPACE, 'xsl:template'),
+ QName(XSL_NAMESPACE, 'xsl:namespace-alias'),
+ ResultElements)
+TopLevelElements = ContentModel(ContentModel.TYPE_ALT, TopLevelElements,
+ ContentModel.QUANT_REP,
+ label='/top-level-elements/',
+ doc=("TopLevelElements is the set of elements"
+ " which have a category of"
+ " top-level-element or are a"
+ " result-element."))
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ForEachElement.py.diff?r1=1.7&r2=1.8
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ForEachElement.py?rev=1.8&content-type=text/vnd.viewcvs-markup
Index: ForEachElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/ForEachElement.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -U2 -r1.7 -r1.8
--- ForEachElement.py 6 Apr 2005 23:05:47 -0000 1.7
+++ ForEachElement.py 27 Nov 2006 16:29:29 -0000 1.8
@@ -22,5 +22,4 @@
class ForEachElement(XsltElement):
- category = CategoryTypes.INSTRUCTION
content = ContentInfo.Seq(
ContentInfo.Rep(ContentInfo.QName(XSL_NAMESPACE, 'xsl:sort')),
@@ -29,6 +28,6 @@
'select' : AttributeInfo.NodeSetExpression(required=1),
}
-
- doesSetup = 1
+
+ doesSetup = True
def setup(self):
@@ -49,5 +48,6 @@
node_set = context.node.childNodes
- state = context.copy()
+ children = [ child.instantiate for child in self.children ]
+ state = context.node, context.position, context.size
pos = 1
size = len(node_set)
@@ -55,8 +55,8 @@
context.node, context.position, context.size = node, pos, size
context.currentNode = node
- for child in self.children:
- child.instantiate(context, processor)
+ for instantiate in children:
+ instantiate(context, processor)
pos += 1
- context.set(state)
+ context.node, context.position, context.size = state
return
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/GenericVariable.py.diff?r1=1.25&r2=1.26
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/GenericVariable.py?rev=1.26&content-type=text/vnd.viewcvs-markup
Index: GenericVariable.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/GenericVariable.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -U2 -r1.25 -r1.26
--- GenericVariable.py 6 Apr 2005 23:05:47 -0000 1.25
+++ GenericVariable.py 27 Nov 2006 16:29:29 -0000 1.26
@@ -9,21 +9,16 @@
"""
-import warnings
-from Ft.Xml import EMPTY_NAMESPACE
-from Ft.Xml.Xslt import XsltElement, XsltException, Error, XSL_NAMESPACE
-from Ft.Xml.Xslt import ContentInfo, AttributeInfo
-from Ft.Xml.XPath import FT_EXT_NAMESPACE
-
-# for variable binding
+from Ft.Xml.Xslt import XsltElement, XSL_NAMESPACE, ContentInfo, AttributeInfo
+from Ft.Xml.Xslt import XsltException, Error
from Ft.Xml.Xslt.StylesheetTree import XsltNode
+__all__ = ['GenericVariableElement', 'PushVariablesNode', 'PopVariablesNode']
+
class GenericVariableElement(XsltElement):
- category = None
content = ContentInfo.Template
legalAttrs = {
- 'name' : AttributeInfo.QName(required=1),
+ 'name' : AttributeInfo.QName(required=True),
'select' : AttributeInfo.Expression(),
- 'f:node-set' : AttributeInfo.YesNoAvt(default='no'),
}
@@ -31,30 +26,15 @@
def setup(self):
- # Check for deprecated f:node-set
- if (FT_EXT_NAMESPACE, 'node-set') in self.attributes:
- warnings.warn("You are using the deprecated f:node-set attribute"
- " on xsl:variable or xsl:param. Please switch to"
- " using exslt:node-set", DeprecationWarning, 2)
-
# check for a bad binding
if self._select and self.children:
raise XsltException(Error.VAR_WITH_CONTENT_AND_SELECT, self._name)
-
- # See the bottom of this file for these helper "nodes"
- binding_save = self.parent.children[0]
- if not isinstance(binding_save, PushVariablesNode):
- # varBindings not yet saved for this level in the stylesheet tree
- parent = self.parent
- binding_save = PushVariablesNode(parent.root, parent.baseUri)
- parent.insertChild(0, binding_save)
- parent.root.primeInstructions.append(binding_save)
return
def instantiate(self, context, processor):
# NOTE: all we want to do is change the varBindings
- context.processorNss = self.namespaces
- context.currentInstruction = self
if self._select:
+ context.processorNss = self.namespaces
+ context.currentInstruction = self
result = self._select.evaluate(context)
elif self.children:
@@ -67,9 +47,4 @@
child.instantiate(context, processor)
result = processor.popResult()
- # Why is the check for childNodes necessary? This will always
- # be an RTF.
- if self.attributes.get((FT_EXT_NAMESPACE, 'node-set')) == 'yes' \
- and hasattr(result, 'childNodes'):
- result = [result]
else:
result = u""
@@ -81,16 +56,9 @@
class PushVariablesNode(XsltNode):
- def __init__(self, root, baseUri):
- self.root = root
- self.baseUri = baseUri
- self.savedVariables = []
- self.popNode = PopVariablesNode(self.savedVariables)
- self._is_primed = False
- return
+ isPseudoNode = True
- def prime(self, processor, context):
- if not self._is_primed:
- self.parent.children.append(self.popNode)
- self._is_primed = True
+ def __init__(self, root, bindingStack):
+ XsltNode.__init__(self, root)
+ self.savedVariables = bindingStack
return
@@ -100,18 +68,16 @@
return
- def isPseudoNode(self):
- return True
-
class PopVariablesNode(XsltNode):
- def __init__(self, savedVariables):
- self.savedVariables = savedVariables
+ isPseudoNode = True
+
+ def __init__(self, root, bindingStack):
+ XsltNode.__init__(self, root)
+ self.savedVariables = bindingStack
return
def instantiate(self, context, processor):
- context.varBindings = self.savedVariables.pop()
+ context.varBindings = self.savedVariables[-1]
+ del self.savedVariables[-1]
return
-
- def isPseudoNode(self):
- return True
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/LiteralElement.py.diff?r1=1.12&r2=1.13
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/LiteralElement.py?rev=1.13&content-type=text/vnd.viewcvs-markup
Index: LiteralElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/LiteralElement.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -U2 -r1.12 -r1.13
--- LiteralElement.py 6 Apr 2005 23:05:47 -0000 1.12
+++ LiteralElement.py 27 Nov 2006 16:29:29 -0000 1.13
@@ -12,4 +12,6 @@
from Ft.Xml.Xslt import XsltElement, XsltRuntimeException, Error
+__all__ = ['LiteralElement']
+
class LiteralElement(XsltElement):
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/Processor.py.diff?r1=1.80&r2=1.81
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/Processor.py?rev=1.81&content-type=text/vnd.viewcvs-markup
Index: Processor.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/Processor.py,v
retrieving revision 1.80
retrieving revision 1.81
diff -U2 -r1.80 -r1.81
--- Processor.py 24 Nov 2006 22:47:36 -0000 1.80
+++ Processor.py 27 Nov 2006 16:29:29 -0000 1.81
@@ -175,4 +175,6 @@
if hasattr(mod,'ExtElements'):
self.extElements.update(mod.ExtElements)
+ reader = self.getStylesheetReader()
+ reader.addExtensionElementMapping(mod.ExtElements)
return
@@ -206,4 +208,7 @@
"""
self.extElements[(namespace, localName)] = klass
+ reader = self.getStylesheetReader()
+ mapping = { (namespace, localName) : klass }
+ reader.addExtensionElementMapping(mapping)
return
@@ -245,28 +250,4 @@
return self._styReader
- def __add_stylesheet(self, stylesheet):
- """
- INTERNAL USE ONLY
- Helper function for adding a stylesheet to the processor. If a
- stylesheet has already been appended, then this method is equivalent
- to having, in an outer "shell" stylesheet, an xsl:import for the most
- recently appended stylesheet followed by an xsl:import for the given
- stylesheet.
- """
- if self.stylesheet:
- for child in self.stylesheet.children:
- child.importIndex += 1000
-
- for child in stylesheet.children:
- self.stylesheet.appendChild(child)
-
- self.stylesheet.reset()
- self.stylesheet.setup()
- else:
- self.stylesheet = stylesheet
-
- self.outputParams = self.stylesheet.outputParams
- return
-
def appendStylesheet(self, iSrc):
"""
@@ -280,6 +261,5 @@
"""
reader = self.getStylesheetReader()
- stylesheet = reader.fromSrc(iSrc, self.extElements)
- self.__add_stylesheet(stylesheet)
+ self.stylesheet = reader.fromSrc(iSrc)
return
@@ -308,13 +288,6 @@
stylesheet is large and complex, like DocBook XSL.
"""
- baseUri = refUri
- if not baseUri:
- # StylesheetTree nodes only ever have baseUri
- # (not baseURI, documentURI, or refUri)
- if hasattr(instance.root, 'baseUri'):
- baseUri = instance.root.baseUri
reader = self.getStylesheetReader()
- stylesheet = reader.fromInstant(instance, baseUri=baseUri, is_import=True)
- self.__add_stylesheet(stylesheet)
+ self.stylesheet = reader.fromInstant(instance, refUri)
return
@@ -339,6 +312,5 @@
document = node.ownerDocument or node
reader = self.getStylesheetReader()
- stylesheet = reader.fromDocument(document, refUri, factory)
- self.__add_stylesheet(stylesheet)
+ self.stylesheet = reader.fromDocument(document, refUri, factory)
return
@@ -647,5 +619,4 @@
if hrefs:
- self.getStylesheetReader()._import_index += 1
for href in hrefs:
# Resolve the PI with the InputSource for the document
@@ -686,4 +657,5 @@
if not self.stylesheet:
raise XsltException(Error.NO_STYLESHEET)
+ self.outputParams = self.stylesheet.outputParams
# Use an internal stream to gather the output only if the caller
@@ -938,5 +910,4 @@
"""
return self.writers[-1]
-
writer = property(writer)
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/Stylesheet.py.diff?r1=1.53&r2=1.54
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/Stylesheet.py?rev=1.54&content-type=text/vnd.viewcvs-markup
Index: Stylesheet.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/Stylesheet.py,v
retrieving revision 1.53
retrieving revision 1.54
diff -U2 -r1.53 -r1.54
--- Stylesheet.py 30 Jul 2006 16:45:47 -0000 1.53
+++ Stylesheet.py 27 Nov 2006 16:29:29 -0000 1.54
@@ -69,8 +69,8 @@
# We don't want ourselves included in these lists since we do the walking
- doesSetup = doesPrime = doesIdle = 0
+ doesSetup = doesPrime = doesIdle = False
- def __init__(self, root, namespaceUri, localName, baseUri):
- XsltElement.__init__(self, root, namespaceUri, localName, baseUri)
+ def __init__(self, *args, **kwds):
+ XsltElement.__init__(self, *args, **kwds)
self.reset1()
return
@@ -357,19 +357,30 @@
if not isinstance(split_name, tuple):
try:
- split_name = self.expandQName(split_name)
+ split_name = context.expandQName(split_name)
except KeyError:
continue
overridden_params[split_name] = value
+ processed, deferred = {}, []
for vnode in self._topVariables[1]:
- self._computeGlobalVar(vnode._name, context, [], [],
- overridden_params, processor)
+ name = vnode._name
+ if vnode.expandedName[1][0] == 'p':
+ if name in overridden_params:
+ context.varBindings[name] = overridden_params[name]
+ else:
+ self._computeGlobalVar(name, context, processed, deferred,
+ processor)
+ #Set up so that later stylesheets will get overridden by
+ #parameter values set in higher-priority stylesheets
+ overridden_params[name] = context.varBindings[name]
+ else:
+ self._computeGlobalVar(name, context, processed, deferred,
+ processor)
self.globalVars.update(context.varBindings)
-
return
def _computeGlobalVar(self, vname, context, processed, deferred,
- overriddenParams, processor):
+ processor):
vnode = self._topVariables[0][vname]
@@ -378,61 +389,27 @@
if vnode in processed:
return
- # Is it an <xsl:param>?
- # expandedName is a tuple (namespace-uri, local-name)
- if vnode.expandedName[1][0] == 'p':
- if vname in overriddenParams:
- context.varBindings[vname] = overriddenParams[vname]
+ while True:
+ depth = len(processor.writers)
+ try:
+ vnode.instantiate(context, processor)
+ except XPath.RuntimeException, e:
+ if e.errorCode == XPath.RuntimeException.UNDEFINED_VARIABLE:
+ #Remove any aborted and possibly unbalanced
+ #outut handlers on the stack
+ depth -= len(processor.writers)
+ if depth:
+ assert depth < 0
+ del processor.writers[depth:]
+ #Defer the current and try evaluating the
+ #one that turned up undefined
+ deferred.append(vnode)
+ self._computeGlobalVar(e.params['key'], context, processed,
+ deferred, processor)
+ deferred.remove(vnode)
+ else:
+ raise
else:
- finished = 0
- while not finished:
- orig_depth = len(processor.writers)
- try:
- vnode.instantiate(context, processor)
- finished = 1
- except XPath.RuntimeException, e:
- if e.errorCode == XPath.RuntimeException.UNDEFINED_VARIABLE:
- #Remove any aborted and possibly unbalanced
- #outut handlers on the stack
- depth = len(processor.writers)
- for i in xrange(depth - orig_depth):
- processor.writers.pop()
- #Defer the current and try evaluating the
- #one that turned up undefined
- deferred.append(vnode)
- self._computeGlobalVar((e.params[0], e.params[1]),
- context, processed, deferred,
- overriddenParams,
- processor)
- deferred.remove(vnode)
- else:
- raise
- #Set up so that later stylesheets will get overridden by
- #parameter values set in higher-priority stylesheets
- overriddenParams[vname] = context.varBindings[vname]
- else:
- finished = 0
- while not finished:
- orig_depth = len(processor.writers)
- try:
- vnode.instantiate(context, processor)
- finished = 1
- except XPath.RuntimeException, e:
- if e.errorCode == XPath.RuntimeException.UNDEFINED_VARIABLE:
- #Remove any aborted and possibly unbalanced
- #output handlers on the stack
- depth = len(processor.writers)
- for i in xrange(depth - orig_depth):
- processor.writers.pop()
- #Defer the current and try evaluating the
- #one that turned up undefined
- deferred.append(vnode)
- self._computeGlobalVar((e.params[0], e.params[1]),
- context, processed, deferred,
- overriddenParams,
- processor)
- deferred.remove(vnode)
- else:
- raise
- processed.append(vnode)
+ break
+ processed[vnode] = True
return
@@ -563,5 +540,5 @@
# with a higher import precedence than what was specified.
if maxImport is not None:
- patterns = filter(lambda x, m=maxImport: x[0][0] < m, patterns)
+ patterns = [ x for x in patterns if x[0][0] < maxImport ]
# Since the patterns may come from different tables, resort them
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/StylesheetHandler.py.diff?r1=1.61&r2=1.62
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/StylesheetHandler.py?rev=1.62&content-type=text/vnd.viewcvs-markup
Index: StylesheetHandler.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/StylesheetHandler.py,v
retrieving revision 1.61
retrieving revision 1.62
diff -U2 -r1.61 -r1.62
--- StylesheetHandler.py 14 Sep 2005 21:38:45 -0000 1.61
+++ StylesheetHandler.py 27 Nov 2006 16:29:29 -0000 1.62
@@ -4,5 +4,5 @@
Stylesheet tree generator
-Copyright 2004 Fourthought, Inc. (USA).
+Copyright 2006 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
@@ -10,18 +10,20 @@
from Ft.Lib import Truncate, UriException
-from Ft.Xml import XML_NAMESPACE, EMPTY_NAMESPACE, Domlette
+from Ft.Xml import XML_NAMESPACE
from Ft.Xml.Lib.XmlString import IsXmlSpace
-from Ft.Xml.Xslt import XSL_NAMESPACE, MessageSource
+from Ft.Xml.Xslt import XSL_NAMESPACE, ContentInfo, AttributeInfo
from Ft.Xml.Xslt import XsltException, XsltParserException, Error
-from Ft.Xml.Xslt import CategoryTypes, BuiltInExtElements
-from Ft.Xml.Xslt import Exslt
+from Ft.Xml.Xslt import BuiltInExtElements, Exslt, StylesheetTree
+from Ft.Xml.Xslt import MessageSource
-from LiteralElement import LiteralElement
-from UndefinedElements import UndefinedXsltElement, UndefinedExtensionElement
+# These are `__all__` safe
+from GenericVariable import *
+from LiteralElement import *
+from UndefinedElements import *
-import StylesheetTree, ContentInfo, AttributeInfo
+__all__ = ['StylesheetHandler']
# Table for load-on-demand of the XSLT elements
-_ELEMENT_MAPPING = {
+ELEMENT_MAPPING = {
'apply-templates' : 'ApplyTemplatesElement.ApplyTemplatesElement',
'apply-imports' : 'ApplyImportsElement.ApplyImportsElement',
@@ -62,5 +64,5 @@
# The XSL attributes allowed on literal elements
-_RESULT_ELEMENT_XSL_ATTRS = {
+RESULT_ELEMENT_XSL_ATTRS = {
'exclude-result-prefixes' : AttributeInfo.Prefixes(),
'extension-element-prefixes' : AttributeInfo.Prefixes(),
@@ -68,8 +70,11 @@
'version' : AttributeInfo.Number(),
}
-_RESULT_ELEMENT_ATTR_INFO = AttributeInfo.AnyAvt()
+RESULT_ELEMENT_ATTR_INFO = AttributeInfo.AnyAvt()
+
+# Cached values for stylesheet tree creation
+_XSLT_ELEMENT_CACHE = {}
+_XSLT_ROOT_VALIDATION = StylesheetTree.XsltRoot.content.compile()
+_LITERAL_ELEMENT_VALIDATION = LiteralElement.content.compile()
-_ELEMENT_CLASSES = {}
-_LEGAL_ATTRS = {}
class ParseState:
@@ -92,5 +97,5 @@
outputNamespaces - set of in-scope namespaces for literal result elements
"""
-
+
def __init__(self, node, validation, localVariables, forwardsCompatible,
currentNamespaces, extensionNamespaces, outputNamespaces):
@@ -111,40 +116,32 @@
"""
- def __init__(self, importIndex=0, globalVars=None, extElements=None,
- visitedStyUris=None, altBaseUris=None, ownerDocument=None):
- self._import_index = importIndex
- if globalVars is None:
- # We need to make sure that the same dictionary is used
- # through the entire processing (even if empty)
- self._global_vars = {}
- else:
- self._global_vars = globalVars
- if extElements is None:
- self._extElements = d = {}
- d.update(Exslt.ExtElements)
- d.update(BuiltInExtElements.ExtElements)
- else:
- self._extElements = extElements
+ # runtime instance variables
+ _input_source = None
+ _locator = None
+ _stylesheet = None
- self._visited_stylesheet_uris = visitedStyUris or {}
+ def __init__(self, altBaseUris=None):
self._alt_base_uris = altBaseUris or []
- self._ownerDoc = ownerDocument
+ self._ownerDoc = None
+ self._import_index = 0
+ self._global_vars = {}
+ self._visited_stylesheet_uris = {}
+ self._documentStateStack = []
+ self._elementStateStack = []
+ self._extElements = {}
+ self._extElements.update(Exslt.ExtElements)
+ self._extElements.update(BuiltInExtElements.ExtElements)
+ self._extensionElementCache = {}
return
def reset(self):
- self._global_vars = {}
+ self._ownerDoc = None
self._import_index = 0
+ self._global_vars = {}
self._visited_stylesheet_uris = {}
- self._ownerDoc = None
+ self._documentStateStack = []
+ self._elementStateStack = []
return
- def clone(self):
- return self.__class__(self._import_index, self._global_vars,
- self._extElements, self._visited_stylesheet_uris,
- self._alt_base_uris, self._ownerDoc)
-
- def getResult(self):
- return self._ownerDoc
-
def addExtensionElementMapping(self, elementMapping):
"""
@@ -158,6 +155,8 @@
You have been warned.
"""
- self._extElements = self._extElements.copy()
self._extElements.update(elementMapping)
+ for name in elementMapping:
+ if name in self._extensionElementCache:
+ del self._extensionElementCache[name]
return
@@ -165,10 +164,17 @@
def setDocumentLocator(self, locator):
+ """
+ Callback interface for SAX.
+ """
+ # Save the current document state for nested parsing (inclusions)
+ document_state = (self._locator, self._stylesheet)
+ self._documentStateStack.append(document_state)
self._locator = locator
+ self._stylesheet = None
return
def startDocument(self):
"""
- ownerDoc is supplied when processing an XSLT import or include.
+ Callback interface for SAX.
"""
# Our root is always a document
@@ -182,16 +188,14 @@
self._ownerDoc = root
- # the stylesheet element instance
- self._stylesheet = None
-
- self._state_stack = [
+ self._elementStateStack.append(
ParseState(node=root,
- validation=root.validator.getValidation(),
+ validation=_XSLT_ROOT_VALIDATION,
localVariables={},
forwardsCompatible=False,
currentNamespaces={'xml' : XML_NAMESPACE, None : None},
extensionNamespaces={},
- outputNamespaces={})
- ]
+ outputNamespaces={},
+ )
+ )
# for recursive include checks for xsl:include/xsl:import
@@ -203,14 +207,76 @@
def endDocument(self):
- self._import_index += 1
- self._locator = None
+ """
+ Callback interface for SAX.
+ """
+ stack = self._elementStateStack
+ state = stack[-1]
+ del stack[-1]
+ root = state.node
+
+ # ----------------------------------------------------------
+ # remove URI from recursive inclusion checking
+ del self._visited_stylesheet_uris[root.baseUri]
+
+ # ----------------------------------------------------------
+ # finalize the children for the document
+ #root.children = tuple(state.nodes)
+
+ # ----------------------------------------------------------
+ # finalize the stylesheet AST
+ if stack:
+ # An xsl:import or xsl:include
+ # Merge the top-level elements into the "parent" stylesheet
+ # IMPLEMENTATION NOTE: stack[-1] is the import/include element,
+ # stack[-2] is the "parent" stylesheet
+ stack[-2].node._merge(self._stylesheet)
+ #parent_node = stack[-2].node
+ #for child in self._stylesheet.children:
+ # child.parent = parent_node
+ else:
+ # A top-most stylesheet
+ stylesheet = self._ownerDoc.stylesheet
+ if stylesheet is not self._stylesheet:
+ # An additional stylesheet (e.g., an <?xml-stylesheet ...?>);
+ # treat it as an xsl:import into the "master" stylesheet.
+ stylesheet.reset()
+
+ # Always update the precedence from the included stylesheet
+ # because it may have contained imports thus increasing its
+ # import precedence.
+ self._import_index += 1
+ stylesheet.importIndex = self._import_index
+
+ # Merge the top-level elements into the "master" stylesheet
+ stylesheet._merge(self._stylesheet)
+ #stylesheet.children += self._stylesheet.children
+ #for child in self._stylesheet.children:
+ # child.parent = stylesheet
+ else:
+ # Prepare for a possible subsequent parse.
+ self._import_index += 1
+
+ # Prepare the "master" stylesheet
+ stylesheet.setup()
+
+ document_state = self._documentStateStack[-1]
+ del self._documentStateStack[-1]
+ self._locator, self._stylesheet = document_state
return
def startPrefixMapping(self, prefix, uri):
+ """
+ Callback interface for SAX.
+ """
self._new_namespaces[prefix] = uri
return
def startElementNS(self, expandedName, qualifiedName, attribs):
- state = ParseState(**self._state_stack[-1].__dict__)
+ """
+ Callback interface for SAX.
+ """
+ parent_state = self._elementStateStack[-1]
+ state = ParseState(**parent_state.__dict__)
+ self._elementStateStack.append(state)
# ----------------------------------------------------------
@@ -221,5 +287,5 @@
d = state.outputNamespaces = state.outputNamespaces.copy()
- for prefix, uri in self._new_namespaces.items():
+ for prefix, uri in self._new_namespaces.iteritems():
if uri not in (XML_NAMESPACE, XSL_NAMESPACE):
d[prefix] = uri
@@ -227,17 +293,17 @@
# reset for next element
self._new_namespaces = {}
-
+
# ----------------------------------------------------------
# get the class defining this element
namespace, local = expandedName
xsl_class = ext_class = None
- category = CategoryTypes.RESULT_ELEMENT
if namespace == XSL_NAMESPACE:
try:
- xsl_class = _ELEMENT_CLASSES[local]
+ xsl_class, validation, validation_token, legal_attrs = \
+ _XSLT_ELEMENT_CACHE[local]
except KeyError:
# We need to try to import (and cache) it
try:
- module = _ELEMENT_MAPPING[local]
+ module = ELEMENT_MAPPING[local]
except KeyError:
if not state.forwardsCompatible:
@@ -245,4 +311,5 @@
self._locator, local)
xsl_class = UndefinedXsltElement
+ validation_token = ContentInfo.RESULT_ELEMENT
else:
parts = module.split('.')
@@ -253,37 +320,37 @@
except KeyError:
raise ImportError('.'.join(parts))
- _ELEMENT_CLASSES[local] = xsl_class
- _LEGAL_ATTRS[xsl_class] = xsl_class.legalAttrs.items()
- xsl_class.validator = ContentInfo.Validator(xsl_class.content)
- category = xsl_class.category
+ validation_token = expandedName
+ validation = xsl_class.content.compile()
+ legal_attrs = xsl_class.legalAttrs.items()
+ _XSLT_ELEMENT_CACHE[local] = (
+ xsl_class, validation, validation_token, legal_attrs)
elif namespace in state.extensionNamespaces:
try:
- ext_class = self._extElements[(namespace, local)]
+ ext_class, validation, legal_attrs = \
+ self._extensionElementCache[expandedName]
except KeyError:
- ext_class = UndefinedExtensionElement
- else:
- if ext_class not in _LEGAL_ATTRS:
- ext_class.validator = \
- ContentInfo.Validator(ext_class.content)
- legal_attrs = ext_class.legalAttrs
- if legal_attrs is not None:
- _LEGAL_ATTRS[ext_class] = legal_attrs.items()
+ try:
+ ext_class = self._extElements[expandedName]
+ except KeyError:
+ ext_class = UndefinedExtensionElement
+ validation = ext_class.content.compile()
+ legal_attrs = ext_class.legalAttrs
+ if legal_attrs is not None:
+ legal_attrs = ext_class.legalAttrs.items()
+ self._extensionElementCache[expandedName] = (
+ ext_class, validation, legal_attrs)
+ validation_token = ContentInfo.RESULT_ELEMENT
+ else:
+ validation = _LITERAL_ELEMENT_VALIDATION
+ validation_token = ContentInfo.RESULT_ELEMENT
+ state.validation = validation
# ----------------------------------------------------------
# verify that this element can be declared here
- validation_else = ContentInfo.ELSE
- if category is not None:
- next = state.validation.get(category)
- if next is None and validation_else in state.validation:
- next = state.validation[validation_else].get(category)
- else:
- next = None
- if next is None:
- next = state.validation.get(expandedName)
- if next is None and validation_else in state.validation:
- next = state.validation[ContentInfo.ELSE].get(expandedName)
- if next is None:
+ try:
+ next = parent_state.validation[validation_token]
+ except KeyError:
#self._debug_validation(expandedName)
- parent = state.node
+ parent = parent_state.node
if parent is self._stylesheet:
if (XSL_NAMESPACE, 'import') == expandedName:
@@ -297,5 +364,5 @@
# element as an exception will occur when/if this element
# is actually instantiated
- if not isinstance(parent, UndefinedExtensionElement):
+ if parent.__class__ is not UndefinedExtensionElement:
raise XsltParserException(Error.ILLEGAL_ELEMENT_CHILD,
self._locator, qualifiedName,
@@ -303,22 +370,23 @@
else:
# save this state for next go round
- self._state_stack[-1].validation = next
+ parent_state.validation = next
# ----------------------------------------------------------
# create the instance defining this element
klass = (xsl_class or ext_class or LiteralElement)
- instance = klass(self._ownerDoc, namespace, local,
- self._locator.getSystemId())
+ state.node = instance = klass(self._ownerDoc, namespace, local,
+ qualifiedName)
+ instance.baseUri = self._locator.getSystemId()
instance.lineNumber = self._locator.getLineNumber()
instance.columnNumber = self._locator.getColumnNumber()
instance.importIndex = self._import_index
instance.namespaces = state.currentNamespaces
- instance.nodeName = qualifiedName
-
+
# -- XSLT element --------------------------------------
if xsl_class:
# Handle attributes in the null-namespace
+ standand_attributes = local in ('stylesheet', 'transform')
inst_dict = instance.__dict__
- for attr_name, attr_info in _LEGAL_ATTRS[xsl_class]:
+ for attr_name, attr_info in legal_attrs:
attr_expanded = (None, attr_name)
if attr_expanded in attribs:
@@ -334,7 +402,7 @@
value = attr_info.prepare(instance, value)
except XsltException, e:
- raise self._mutate_exception(e)
+ raise self._mutate_exception(e, qualifiedName)
- if local in ('stylesheet', 'transform'):
+ if standand_attributes:
self._stylesheet = instance
self._handle_standard_attr(state, instance, attr_name,
@@ -356,5 +424,6 @@
self._locator, attr_name, qualifiedName)
else:
- instance.attributes[expanded] = attribs[expanded]
+ instance.setAttribute(attr_ns, attr_name,
+ attribs[expanded])
# XSLT Spec 2.6 - Combining Stylesheets
@@ -364,9 +433,9 @@
# -- extension element ---------------------------------
elif ext_class:
- validate_attributes = (ext_class in _LEGAL_ATTRS)
+ validate_attributes = (legal_attrs is not None)
if validate_attributes:
# Handle attributes in the null-namespace
inst_dict = instance.__dict__
- for attr_name, attr_info in _LEGAL_ATTRS[ext_class]:
+ for attr_name, attr_info in legal_attrs:
attr_expanded = (None, attr_name)
if attr_expanded in attribs:
@@ -382,5 +451,5 @@
value = attr_info.prepare(instance, value)
except XsltException, e:
- raise self._mutate_exception(e)
+ raise self._mutate_exception(e, qualifiedName)
if '-' in attr_name:
attr_name = attr_name.replace('-', '_')
@@ -402,5 +471,5 @@
attr_name, value)
else:
- instance.attributes[expanded] = value
+ instance.setAttribute(attr_ns, attr_name, value)
# -- literal result element ----------------------------
@@ -415,7 +484,6 @@
attr_local, value)
else:
- instance.attributes[expanded] = value
# prepare attributes for literal output
- value = _RESULT_ELEMENT_ATTR_INFO.prepare(instance, value)
+ value = RESULT_ELEMENT_ATTR_INFO.prepare(instance, value)
attr_qname = attribs.getQNameByName(expanded)
output_attrs.append((attr_qname, attr_ns, value))
@@ -427,16 +495,9 @@
# Check for top-level result-element in null namespace
- parent = state.node
- if parent is self._stylesheet and \
+ if parent_state.node is self._stylesheet and \
not namespace and not state.forwardsCompatible:
raise XsltParserException(Error.ILLEGAL_ELEMENT_CHILD,
self._locator, qualifiedName,
- parent.nodeName)
-
- # ----------------------------------------------------------
- # update depth information
- state.node = instance
- state.validation = instance.validator.getValidation()
- self._state_stack.append(state)
+ parent_state.node.nodeName)
if instance.doesPrime:
@@ -447,8 +508,47 @@
def endElementNS(self, expandedName, qualifiedName):
- state = self._state_stack.pop()
+ """
+ Callback interface for SAX.
+ """
+ stack = self._elementStateStack
+ state = stack[-1]
+ del stack[-1]
+ parent_state = stack[-1]
element = state.node
- if len(self._state_stack) == 1 and isinstance(element, LiteralElement):
+
+ # ----------------------------------------------------------
+ # verify that this element has all required content
+ try:
+ state.validation[ContentInfo.END_ELEMENT]
+ except KeyError:
+ if expandedName == (XSL_NAMESPACE, u'choose'):
+ raise XsltParserException(Error.CHOOSE_REQUIRES_WHEN,
+ self._locator)
+ raise
+
+ # ----------------------------------------------------------
+ # setup variable context
+ if state.localVariables is not parent_state.localVariables:
+ # add context save/restore nodes
+ binding_stack = []
+ node = PushVariablesNode(self._ownerDoc, binding_stack)
+ element.insertChild(0, node)
+ node = PopVariablesNode(self._ownerDoc, binding_stack)
+ element.appendChild(node)
+
+ # ----------------------------------------------------------
+ # finalize the children for this element
+ #element.children = tuple(state.nodes)
+ #for child in element.children:
+ # if child.doesSetup:
+ #s child.setup()
+ del state
+
+ # ----------------------------------------------------------
+ # update parent state
+ parent_node = parent_state.node
+ if self._stylesheet is None and parent_node is element.root:
# a literal result element as stylesheet
+ assert isinstance(element, LiteralElement), element
try:
version = element._version
@@ -457,4 +557,7 @@
self._locator)
+ # Reset the root's validation as it has already seen an element.
+ parent_state.validation = _XSLT_ROOT_VALIDATION
+
# FIXME: use the prefix from the document for the XSL namespace
stylesheet = (XSL_NAMESPACE, u'stylesheet')
@@ -467,70 +570,73 @@
# make this element the template's content
- self._state_stack[-1].node.appendChild(element)
+ # Note, this MUST index the stack as the stack has changed
+ # due to the startElementNS() calls.
+ stack[-1].node.appendChild(element)
self.endElementNS(template, u'xsl:template')
self.endElementNS(stylesheet, u'xsl:stylesheet')
- else:
- self._state_stack[-1].node.appendChild(element)
+ return
- if expandedName in ((XSL_NAMESPACE, u'variable'),
- (XSL_NAMESPACE, u'param')):
- name = element._name
- # one for the root and one for the stylesheet or
- # a literal result element as stylesheet
- if len(self._state_stack) > 2 or \
- isinstance(self._state_stack[-1].node, LiteralElement):
- # local variables
- # it is safe to ignore import precedence here
- local_vars = self._state_stack[-1].localVariables
- if name in local_vars:
- raise XsltParserException(Error.ILLEGAL_SHADOWING,
- self._locator, name)
- # Copy on use
- if local_vars is self._state_stack[-2].localVariables:
- local_vars = local_vars.copy()
- self._state_stack[-1].localVariables = local_vars
- local_vars[name] = True
- else:
- # global variables
- existing = self._global_vars.get(name, -1)
+ parent_node.appendChild(element)
+
+ if isinstance(element, GenericVariableElement):
+ name = element._name
+ if parent_node is self._stylesheet:
+ # global variables
+ if name in self._global_vars:
+ existing = self._global_vars[name]
if self._import_index > existing:
self._global_vars[name] = self._import_index
elif self._import_index == existing:
- raise XsltParserException(Error.DUPLICATE_TOP_LEVEL_VAR,
- self._locator, name)
+ raise XsltParserException(
+ Error.DUPLICATE_TOP_LEVEL_VAR,
+ self._locator, name)
+ else:
+ self._global_vars[name] = self._import_index
+ else:
+ # local variables
+ # it is safe to ignore import precedence here
+ local_vars = parent_state.localVariables
+ if name in local_vars:
+ raise XsltParserException(Error.ILLEGAL_SHADOWING,
+ self._locator, name)
+ # Copy on use
+ if local_vars is stack[-2].localVariables:
+ local_vars = local_vars.copy()
+ parent_state.localVariables = local_vars
+ local_vars[name] = True
return
def characters(self, data):
- state = self._state_stack[-1]
+ """
+ Callback interface for SAX.
+ """
+ parent_state = self._elementStateStack[-1]
# verify that the current element can have text children
- validation = state.validation
- token = ContentInfo.TEXT_NODE
- next = validation.get(token)
- if next is None and ContentInfo.ELSE in validation:
- next = validation[ContentInfo.ELSE].get(token)
- if next is None:
+ try:
+ next = parent_state.validation[ContentInfo.TEXT_NODE]
+ except KeyError:
# If the parent can have element children, but not text nodes,
# ignore pure whitespace nodes. This clarification is from
# XSLT 2.0 [3.4] Whitespace Stripping.
# e.g. xsl:stylesheet, xsl:apply-templates, xsl:choose
- if not (ContentInfo.EMPTY not in validation and IsXmlSpace(data)):
+ #self._debug_validation(ContentInfo.TEXT_NODE)
+ if (ContentInfo.EMPTY in parent_state.validation or
+ not IsXmlSpace(data)):
raise XsltParserException(Error.ILLEGAL_TEXT_CHILD_PARSE,
self._locator,
repr(Truncate(data, 10)),
- state.node.nodeName)
- #self._debug_validation(expandedName)
+ parent_state.node.nodeName)
+ #self._debug_validation(ContentInfo.TEXT_NODE)
else:
# update validation
- state.validation = next
+ parent_state.validation = next
- node = StylesheetTree.XsltText(self._ownerDoc,
- self._locator.getSystemId(),
- data)
- state.node.appendChild(node)
+ node = StylesheetTree.XsltText(self._ownerDoc, data)
+ parent_state.node.appendChild(node)
return
# -- utility functions ---------------------------------------------
-
+
def _combine_stylesheet(self, href, is_import):
hint = is_import and 'STYLESHEET IMPORT' or 'STYLESHEET INCLUDE'
@@ -558,33 +664,10 @@
raise XsltParserException(Error.CIRCULAR_INCLUDE,
self._locator, new_source.uri)
- else:
- self._visited_stylesheet_uris[new_source.uri] = True
-
- # Create a new reader to handle the inclusion
- include = self.clone().fromSrc(new_source)
+ self.fromSrc(new_source)
- # Make sure we detect circular imports/includes, but not other duplicates
- del self._visited_stylesheet_uris[new_source.uri]
-
- # The stylesheet containing the import will always be one higher
- # than the imported stylesheet.
- #
- # For example:
- # stylesheet A imports stylesheets B and C in that order,
- # stylesheet B imports stylesheet D,
- # stylesheet C imports stylesheet E.
- # The resulting import precedences are:
- # A=4, C=3, E=2, B=1, D=0
-
- # Always update the precedence from the included stylesheet
- # because it may have contained imports thus increasing its
- # import precedence.
- import_index = include.importIndex + is_import
- self._stylesheet.importIndex = self._import_index = import_index
-
- # merge the top-level elements
- self._stylesheet.children.extend(include.children)
- for child in include.children:
- child.parent = self._stylesheet
+ self._import_index += is_import
+ # Always update the precedence as the included stylesheet may have
+ # contained imports thus increasing the import precedence.
+ self._stylesheet.importIndex = self._import_index
return
@@ -619,5 +702,5 @@
self._locator,
prefix or '#default')
- # remove all matching namespace URIs
+ # remove all matching namespace URIs
for output_prefix, output_uri in out.items():
if output_uri == uri:
@@ -636,5 +719,5 @@
attributeName, value):
try:
- attr_info = _RESULT_ELEMENT_XSL_ATTRS[attributeName]
+ attr_info = RESULT_ELEMENT_XSL_ATTRS[attributeName]
except KeyError:
raise XsltParserException(Error.ILLEGAL_XSL_NAMESPACE_ATTR,
@@ -645,32 +728,27 @@
return
- def _mutate_exception(self, exception):
- msg = MessageSource.POSITION_INFO % (self._locator.getSystemId(),
- self._locator.getLineNumber(),
- self._locator.getColumnNumber(),
- exception.message)
- exception.message = msg
+ def _mutate_exception(self, exception, elementName):
+ assert isinstance(exception, XsltException)
+ exception.message = MessageSource.EXPRESSION_POSITION_INFO % (
+ self._locator.getSystemId(), self._locator.getLineNumber(),
+ self._locator.getColumnNumber(), elementName, exception.message)
return exception
-
# -- debugging routines --------------------------------------------
-
- def _debug_validation(self, token=None, next=None):
+
+ def _debug_validation(self, token=None):
from pprint import pprint
- state = self._state_stack[-1]
+ state = self._elementStateStack[-1]
parent = state.node
print '='*60
print 'parent =',parent
print 'parent class =',parent.__class__
- print 'content expression =', parent.validator
+ print 'parent content =', parent.content
print 'initial validation'
- pprint(parent.validator.getValidation())
+ pprint(parent.content.compile())
print 'current validation'
pprint(state.validation)
if token:
print 'token', token
- if next:
- print 'next validation'
- pprint(next)
print '='*60
return
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/StylesheetReader.py.diff?r1=1.56&r2=1.57
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/StylesheetReader.py?rev=1.57&content-type=text/vnd.viewcvs-markup
Index: StylesheetReader.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/StylesheetReader.py,v
retrieving revision 1.56
retrieving revision 1.57
diff -U2 -r1.56 -r1.57
--- StylesheetReader.py 29 Oct 2005 05:34:25 -0000 1.56
+++ StylesheetReader.py 27 Nov 2006 16:29:29 -0000 1.57
@@ -9,4 +9,6 @@
"""
+__all__ = ['StylesheetReader']
+
import cStringIO
from xml.dom import Node
@@ -27,5 +29,4 @@
return
-
# Whitespace stripping rules for a stylesheet:
# preserve all whitespace within xsl:text elements;
@@ -44,23 +45,4 @@
avoids creating a Domlette document for each document it reads.
"""
- def __init__(self, altBaseUris=None, ownerDocument=None,
- importIndex=0, globalVars=None, extElements=None,
- visitedStyUris=None):
- StylesheetHandler.__init__(self, importIndex, globalVars, extElements,
- visitedStyUris)
- self._alt_base_uris = altBaseUris or []
- self._ownerDoc = ownerDocument
- return
-
- def reset(self):
- StylesheetHandler.reset(self)
- self._ownerDoc = None
- self._input_source = None
- return
-
- def clone(self):
- return self.__class__(self._alt_base_uris, self._ownerDoc,
- self._import_index, self._global_vars,
- self._extElements, self._visited_stylesheet_uris)
def fromInstant(self, instant, baseUri='', is_import=0):
@@ -179,5 +161,5 @@
properties = []
stylesheet = self._parseSrc(isrc, features, properties)
-
+
# Cache the string content for subsequent uses
# e.g., xsl:import/xsl:include and document()
@@ -187,6 +169,4 @@
def _parseSrc(self, isrc, features, properties):
- self._input_source = isrc
-
parser = Sax.CreateParser()
parser.setContentHandler(self)
@@ -200,18 +180,16 @@
parser.setProperty(propertyname, value)
+ prev_source = self._input_source
try:
- parser.parse(isrc)
- except SAXParseException, e:
- e = e.getException() or e
- if isinstance(e, XsltException):
- raise e
- raise XsltException(Error.STYLESHEET_PARSE_ERROR, isrc.uri, e)
-
- self._input_source = None
-
- root = self._state_stack[0].node
- if root is self._ownerDoc:
- # the top-most stylesheet
- root.stylesheet.setup()
+ self._input_source = isrc
+ try:
+ parser.parse(isrc)
+ except SAXParseException, e:
+ e = e.getException() or e
+ if isinstance(e, XsltException):
+ raise e
+ raise XsltException(Error.STYLESHEET_PARSE_ERROR, isrc.uri, e)
+ finally:
+ self._input_source = prev_source
- return root.stylesheet
+ return self._ownerDoc.stylesheet
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/StylesheetTree.py.diff?r1=1.23&r2=1.24
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/StylesheetTree.py?rev=1.24&content-type=text/vnd.viewcvs-markup
Index: StylesheetTree.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/StylesheetTree.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -U2 -r1.23 -r1.24
--- StylesheetTree.py 11 May 2005 16:11:05 -0000 1.23
+++ StylesheetTree.py 27 Nov 2006 16:29:29 -0000 1.24
@@ -4,20 +4,12 @@
Node classes for the stylesheet tree
-Copyright 2004 Fourthought, Inc. (USA).
+Copyright 2006 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""
-from Ft.Xml import EMPTY_NAMESPACE
-from Ft.Xml.Domlette import GetAllNs
-from Ft.Xml.Xslt import XSL_NAMESPACE, XsltException, XsltRuntimeException, Error
-from Ft.Xml.Xslt import AttributeValueTemplate
-from Ft.Xml.Xslt import CategoryTypes
-from Ft.Xml.Xslt import ContentInfo
-
-from Ft.Xml.XPath import parser
-_xpath_parser = parser
-from Ft.Xml.Xslt import parser
-_xpattern_parser = parser
-del parser
+
+from Ft.Xml.Xslt import XSL_NAMESPACE, ContentInfo
+
+__all__ = ['XsltNode', 'XsltRoot', 'XsltElement', 'XsltText']
class XsltNode:
@@ -41,16 +33,15 @@
doesPrime = False
doesIdle = False
+ isPseudoNode = False
def isLastChild(self):
siblings = self.parent.children
- if siblings.index(self) == len(siblings) - 1:
- return 1
+ if siblings[-1] is self:
+ return True
else:
- isLast = 1
- for node in siblings[siblings.index(self)+1:]:
- if not node.isPseudoNode():
- isLast = 0
- break
- return isLast
+ index = -1
+ while siblings[index].isPseudoNode:
+ index -= 1
+ return siblings[-1] is self
def setup(self):
@@ -66,7 +57,4 @@
return
- def isPseudoNode(self):
- return False
-
def pprint(self, _indent=''):
print _indent + str(self)
@@ -77,15 +65,25 @@
return
+ def __str__(self):
+ ptr = id(self)
+ if ptr < 0:
+ ptr += 0x100000000
+ return "<%s at 0x%x>" % (self.__class__.__name__, ptr)
class XsltRoot(XsltNode):
- content = ContentInfo.Alt(ContentInfo.QName(XSL_NAMESPACE, 'xsl:stylesheet'),
- ContentInfo.QName(XSL_NAMESPACE, 'xsl:transform'),
- ContentInfo.ResultElements)
-
- validator = ContentInfo.Validator(content)
+ content = ContentInfo.Alt(
+ ContentInfo.QName(XSL_NAMESPACE, 'xsl:stylesheet'),
+ ContentInfo.QName(XSL_NAMESPACE, 'xsl:transform'),
+ ContentInfo.ResultElements)
nodeName = u'#document'
+ def children(self):
+ if self.stylesheet:
+ return (self.stylesheet,)
+ return ()
+ children = property(children)
+
def __init__(self, baseUri):
self.root = self
@@ -128,17 +126,10 @@
self.primeInstructions = []
self.idleInstructions = []
- self.stylesheet = None
- self.children = []
return
def appendChild(self, child):
- # The validator ensures that only one child will be added
- child.parent = self
+ assert not self.stylesheet
self.stylesheet = child
- self.children = [child]
- return
-
- def __str__(self):
- return "<XsltRoot at 0x%x>" % id(self)
+ child.parent = self
@@ -146,13 +137,11 @@
class XsltElement(XsltNode):
- category = CategoryTypes.RESULT_ELEMENT
content = ContentInfo.Template
- validator = ContentInfo.Validator(content)
legalAttrs = None # this means no error checking or defaulting
- def __init__(self, root, namespaceUri, localName, baseUri):
+ def __init__(self, root, namespaceUri, localName, nodeName):
self.root = root
- self.baseUri = baseUri
self.expandedName = (namespaceUri, localName)
+ self.nodeName = nodeName
self.children = []
self.attributes = {}
@@ -160,83 +149,38 @@
return
- def insertChild(self, index, child):
- """INTERNAL USE ONLY"""
- self.children.insert(index, child)
- child.parent = self
- if child.doesSetup:
- child.setup()
- return
-
- def appendChild(self, child):
- """INTERNAL USE ONLY"""
- self.children.append(child)
- child.parent = self
- if child.doesSetup:
- child.setup()
- return
-
- def parseAVT(self, avt):
- """DEPRECATED: specify an attribute in 'legalAttrs' instead."""
- if avt is None: return None
- try:
- return AttributeValueTemplate.AttributeValueTemplate(avt)
- except SyntaxError, error:
- raise XsltException(Error.INVALID_AVT, avt, self.baseUri,
- self.lineNumber, self.columnNumber,
- str(error))
- except XsltException, error:
- raise XsltException(Error.INVALID_AVT, avt, self.baseUri,
- self.lineNumber, self.columnNumber,
- error.args[0])
-
- def parseExpression(self, expression):
- """DEPRECATED: specify an attribute in 'legalAttrs' instead."""
- if expression is None: return None
- p = _xpath_parser.new()
- try:
- return p.parse(expression)
- except SyntaxError, error:
- raise XsltException(Error.INVALID_EXPRESSION, expression,
- self.baseUri, self.lineNumber,
- self.columnNumber, str(error))
-
- def parsePattern(self, pattern):
- """DEPRECATED: specify an attribute in 'legalAttrs' instead."""
- if pattern is None: return None
- p = _xpattern_parser.new()
- try:
- return p.parse(pattern)
- except SyntaxError, error:
- raise XsltException(Error.INVALID_PATTERN, pattern,
- self.baseUri, self.lineNumber,
- self.columnNumber, str(error))
-
- def splitQName(self, qname):
- """DEPRECATED: specify an attribute in 'legalAttrs' instead."""
- if not qname: return None
- index = qname.find(':')
- if index != -1:
- split = (qname[:index], qname[index+1:])
- else:
- split = (None, qname)
- return split
-
- def expandQName(self, qname, refNode=None):
- """DEPRECATED: specify an attribute in 'legalAttrs' instead."""
- if not qname: return None
- if refNode:
- namespaces = GetAllNs(refNode)
- else:
- namespaces = self.namespaces
- prefix, local = self.splitQName(qname)
- if prefix:
- try:
- expanded = (namespaces[prefix], local)
- except KeyError:
- raise XsltRuntimeException(Error.UNDEFINED_PREFIX,
- self, prefix)
- else:
- expanded = (EMPTY_NAMESPACE, local)
- return expanded
+ def appendChild(self, newChild):
+ assert self.parent is None
+ self.children.append(newChild)
+ newChild.parent = self
+ if newChild.doesSetup:
+ newChild.setup()
+ return
+
+ def insertChild(self, index, newChild):
+ assert self.parent is None
+ self.children.insert(index, newChild)
+ newChild.parent = self
+ if newChild.doesSetup:
+ newChild.setup()
+ return
+
+ def removeChild(self, oldChild):
+ assert self.parent is None
+ self.children.remove(oldChild)
+ oldChild.parent = None
+
+ def replaceChild(self, oldChild, newChild):
+ assert self.parent is None
+ index = self.children.index(oldChild)
+ oldChild.parent = None
+ self.children[index] = newChild
+ newChild.parent = self
+ if newChild.doesSetup:
+ newChild.setup()
+ return
+
+ def setAttribute(self, namespaceURI, localName, value):
+ assert self.parent is None
+ self.attributes[namespaceURI, localName] = value
def instantiate(self, context, processor):
@@ -265,9 +209,11 @@
def __str__(self):
- #FIXME: Should this use self.__class__ or sth rather than hardcoding "XsltElement"?
- return ("<XsltElement at 0x%x:"
- " name %r, %d attributes, %d children, precedence %d>") % (
- id(self), self.nodeName, len(self.attributes), len(self.children),
- self.importIndex)
+ ptr = id(self)
+ if ptr < 0:
+ ptr += 0x100000000
+ return ("<%s at 0x%x: name %r, %d attributes, %d children,"
+ " precedence %d>") % (self.__class__.__name__, ptr,
+ self.nodeName, len(self.attributes),
+ len(self.children), self.importIndex)
@@ -276,7 +222,10 @@
nodeName = u'#text'
- def __init__(self, root, baseUri, data):
+ def baseUri(self):
+ return self.parent.baseUri
+ baseUri = property(baseUri)
+
+ def __init__(self, root, data):
self.root = root
- self.baseUri = baseUri
self.data = data
return
@@ -287,7 +236,11 @@
def __str__(self):
- if len(self.data) > 20:
- data = self.data[:20] + '...'
- else:
- data = self.data
- return "<XsltText at 0x%x: %s>" % (id(self), repr(data))
+ ptr = id(self)
+ if ptr < 0:
+ ptr += 0x100000000
+ data = self.data
+ if len(data) > 20:
+ data = data[:10] + '...' + data[-10:]
+ return "<%s at 0x%x: %r>" % (self.__class__.__name__, ptr, data)
+
+from cStylesheetTree import *
\ No newline at end of file
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/TemplateElement.py.diff?r1=1.11&r2=1.12
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/TemplateElement.py?rev=1.12&content-type=text/vnd.viewcvs-markup
Index: TemplateElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/TemplateElement.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -U2 -r1.11 -r1.12
--- TemplateElement.py 6 Apr 2005 23:05:47 -0000 1.11
+++ TemplateElement.py 27 Nov 2006 16:29:29 -0000 1.12
@@ -19,5 +19,5 @@
class TemplateElement(XsltElement):
- category = CategoryTypes.TOP_LEVEL_ELEMENT
+
content = ContentInfo.Seq(
ContentInfo.Rep(ContentInfo.QName(XSL_NAMESPACE, 'xsl:param')),
@@ -30,4 +30,15 @@
}
+ doesSetup = True
+
+ def setup(self):
+ self._params = [ (child, child._name) for child in self.children
+ if child.expandedName == (XSL_NAMESPACE, 'param') ]
+ if self._params:
+ self._instructions = self.children[len(self._params)+1:-1]
+ else:
+ self._instructions = self.children
+ return
+
def getTemplateInfo(self, position):
infos = []
@@ -68,23 +79,30 @@
def instantiate(self, context, processor, params=None):
- params = params or {}
+ if params is None:
+ params = {}
+
+ if self._params:
+ varBindings = context.varBindings
+ context.varBindings = varBindings.copy()
while 1:
context.recursiveParams = None
- for child in self.children:
- if child.expandedName == (XSL_NAMESPACE, 'param'):
- value = params.get(child._name)
- if value is not None:
- context.varBindings[child._name] = value
- else:
- child.instantiate(context, processor)
+ for child, param in self._params:
+ if param in params:
+ context.varBindings[param] = params[param]
else:
child.instantiate(context, processor)
+ for child in self._instructions:
+ child.instantiate(context, processor)
+
if context.recursiveParams is not None:
# Update the params from the values given in recursiveParams.
- params.update(context.recursiveParams)
+ params = context.recursiveParams
else:
break
+
+ if self._params:
+ context.varBindings = varBindings
return
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/TextElement.py.diff?r1=1.6&r2=1.7
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/TextElement.py?rev=1.7&content-type=text/vnd.viewcvs-markup
Index: TextElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/TextElement.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -U2 -r1.6 -r1.7
--- TextElement.py 6 Apr 2005 23:05:47 -0000 1.6
+++ TextElement.py 27 Nov 2006 16:29:29 -0000 1.7
@@ -4,18 +4,13 @@
Implementation of the xsl:text element.
-Copyright 2005 Fourthought, Inc. (USA).
+Copyright 2006 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""
-from xml.dom import Node
-
-from Ft.Xml import EMPTY_NAMESPACE
-from Ft.Xml.Xslt import XsltElement, XsltException, Error, XSL_NAMESPACE
-from Ft.Xml.Xslt import CategoryTypes, ContentInfo, AttributeInfo
-
+from Ft.Xml.Xslt import XsltElement, ContentInfo, AttributeInfo
class TextElement(XsltElement):
- category = CategoryTypes.INSTRUCTION
+
content = ContentInfo.Text
legalAttrs = {
@@ -23,11 +18,19 @@
}
- def instantiate(self, context, processor):
+ doesSetup = True
+
+ def setup(self):
if self.children:
- value = self.children[0].data
+ self._value = self.children[0].data
+ else:
+ self._value = None
+ return
+
+ def instantiate(self, context, processor):
+ if self._value:
if self._disable_output_escaping:
- processor.writers[-1].text(value, escapeOutput=False)
+ processor.writers[-1].text(self._value, False)
else:
- processor.writers[-1].text(value)
+ processor.writers[-1].text(self._value)
return
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/UndefinedElements.py.diff?r1=1.3&r2=1.4
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/UndefinedElements.py?rev=1.4&content-type=text/vnd.viewcvs-markup
Index: UndefinedElements.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/UndefinedElements.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -U2 -r1.3 -r1.4
--- UndefinedElements.py 6 Apr 2005 23:05:47 -0000 1.3
+++ UndefinedElements.py 27 Nov 2006 16:29:29 -0000 1.4
@@ -12,4 +12,6 @@
from Ft.Xml.Xslt import CategoryTypes, ContentInfo
+__all__ = ['UndefinedXsltElement', 'UndefinedExtensionElement']
+
class _UndefinedElement(XsltElement):
@@ -49,3 +51,3 @@
*self.expandedName)
-
+
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ValueOfElement.py.diff?r1=1.8&r2=1.9
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/ValueOfElement.py?rev=1.9&content-type=text/vnd.viewcvs-markup
Index: ValueOfElement.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/ValueOfElement.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -U2 -r1.8 -r1.9
--- ValueOfElement.py 6 Apr 2005 23:05:47 -0000 1.8
+++ ValueOfElement.py 27 Nov 2006 16:29:29 -0000 1.9
@@ -9,7 +9,7 @@
"""
+from Ft.Xml.XPath import Conversions
from Ft.Xml.Xslt import XsltElement
from Ft.Xml.Xslt import CategoryTypes, ContentInfo, AttributeInfo
-from Ft.Xml.XPath import Conversions
class ValueOfElement(XsltElement):
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/XPathExtensions.py.diff?r1=1.9&r2=1.10
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/XPathExtensions.py?rev=1.10&content-type=text/vnd.viewcvs-markup
Index: XPathExtensions.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/XPathExtensions.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -U2 -r1.9 -r1.10
--- XPathExtensions.py 6 Apr 2005 23:05:47 -0000 1.9
+++ XPathExtensions.py 27 Nov 2006 16:29:29 -0000 1.10
@@ -33,5 +33,5 @@
def __str__(self):
return "<SortedExpr at 0x%x: %s>" % (id(self), repr(self.expression))
-
+
def compare(self, (node1, keys1), (node2, keys2)):
for i in xrange(len(self.cmps)):
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/XsltContext.py.diff?r1=1.14&r2=1.15
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/XsltContext.py?rev=1.15&content-type=text/vnd.viewcvs-markup
Index: XsltContext.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/XsltContext.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -U2 -r1.14 -r1.15
--- XsltContext.py 10 Dec 2005 17:54:49 -0000 1.14
+++ XsltContext.py 27 Nov 2006 16:29:29 -0000 1.15
@@ -4,19 +4,15 @@
Context and state information for XSLT processing
-Copyright 2003 Fourthought, Inc. (USA).
+Copyright 2006 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""
-import Exslt, BuiltInExtFunctions
from Ft.Lib.Uri import UriDict
-from Ft.Xml import EMPTY_NAMESPACE
-from Ft.Xml.XPath import Context, Util, RuntimeException
-from Ft.Xml.Xslt import XsltFunctions
+from Ft.Xml.Lib.XmlString import SplitQName
+from Ft.Xml.XPath import Context, RuntimeException
+from Ft.Xml.Xslt import XsltFunctions, BuiltInExtFunctions, Exslt
-
-#NOTE: Some of the state information maintained here would probably be better
-#managed by the processor, but until Python pre-GC support is phased out,
-#the current arrangement will have to do
+__all__ = ['XsltContext']
class XsltContext(Context.Context):
@@ -27,28 +23,10 @@
functions.update(BuiltInExtFunctions.ExtFunctions)
- def __init__(self,
- node,
- position=1,
- size=1,
- currentNode=None,
- varBindings=None,
- processorNss=None,
- stylesheet=None,
- processor=None,
- mode=None,
- extModuleList = None,
- extFunctionMap = None,
- ):
-
-
- Context.Context.__init__(self,
- node,
- position,
- size,
- varBindings,
- processorNss,
- extModuleList,
- extFunctionMap
- )
+ def __init__(self, node, position=1, size=1, currentNode=None,
+ varBindings=None, processorNss=None, stylesheet=None,
+ processor=None, mode=None, extModuleList=None,
+ extFunctionMap=None):
+ Context.Context.__init__(self, node, position, size, varBindings,
+ processorNss, extModuleList, extFunctionMap)
self.currentNode = currentNode
self.stylesheet = stylesheet
@@ -56,5 +34,4 @@
self.processor = processor
self.documents = UriDict()
- self.rtfs = []
self.currentInstruction = None
self.recursiveParams = None
@@ -67,24 +44,20 @@
return
- def splitQName(self, qname):
- if not qname: return None
- index = qname.find(':')
- if index != -1:
- split = (qname[:index], qname[index+1:])
- else:
- split = (None, qname)
- return split
-
- def expandQName(self, qname):
- if not qname: return None
- prefix, local = self.splitQName(qname)
+ def splitQName(self, qualifiedName):
+ if not qualifiedName: return None
+ return SplitQName(qualifiedName)
+
+ def expandQName(self, qualifiedName):
+ if not qualifiedName: return None
+ prefix, local = SplitQName(qualifiedName)
if prefix:
try:
- expanded = (self.processorNss[prefix], local)
+ namespace = self.processorNss[prefix]
except KeyError:
- raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix)
+ raise RuntimeException(RuntimeException.UNDEFINED_PREFIX,
+ prefix)
else:
- expanded = (EMPTY_NAMESPACE, local)
- return expanded
+ namespace = None
+ return (namespace, local)
def setProcessState(self, execNode):
@@ -94,16 +67,18 @@
def clone(self):
- return XsltContext(self.node, self.position, self.size,
- self.currentNode, self.varBindings.copy(),
- self.processorNss, self.stylesheet,
- self.processor, self.mode)
+ return self.__class__(node=self.node,
+ position=self.position,
+ size=self.size,
+ currentNode=self.currentNode,
+ varBindings=self.varBindings.copy(),
+ processorNss=self.processorNss,
+ stylesheet=self.stylesheet,
+ processor=self.processor,
+ mode=self.mode)
def __repr__(self):
- return '<XsltContext at %x: node %s, position %d, size %d, mode %r>' % (
- id(self),
- repr(self.node),
- self.position,
- self.size,
- self.mode
- )
-
+ ptr = id(self)
+ if ptr < 0:
+ ptr += 0x100000000
+ return ('<XsltContext at 0x%x: node %r, position %d, size %d, mode %r'
+ '>' % (ptr, self.node, self.position, self.size, self.mode))
ViewCVS diff:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/XsltFunctions.py.diff?r1=1.46&r2=1.47
ViewCVS view:
http://cvs.4suite.org/viewcvs/4Suite/Ft/Xml/Xslt/XsltFunctions.py?rev=1.47&content-type=text/vnd.viewcvs-markup
Index: XsltFunctions.py
===================================================================
RCS file: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/XsltFunctions.py,v
retrieving revision 1.46
retrieving revision 1.47
diff -U2 -r1.46 -r1.47
--- XsltFunctions.py 2 Aug 2005 22:43:01 -0000 1.46
+++ XsltFunctions.py 27 Nov 2006 16:29:29 -0000 1.47
@@ -17,7 +17,5 @@
from Ft.Xml.XPath.XPathTypes import NodesetType
from Ft.Xml.Xslt import XsltRuntimeException, Error, XSL_NAMESPACE
-
-# is there no better list of implemented core XSLT elements?
-from Ft.Xml.Xslt.StylesheetHandler import _ELEMENT_MAPPING
+from Ft.Xml.Xslt.StylesheetHandler import ELEMENT_MAPPING
def Document(context, object, nodeSet=None):
@@ -334,9 +332,9 @@
if namespaceURI == XSL_NAMESPACE:
- available = localName in _ELEMENT_MAPPING
- elif namespaceURI == EMPTY_NAMESPACE:
- available = False
- else:
+ available = localName in ELEMENT_MAPPING
+ elif namespaceURI:
available = expandedName in context.processor.extElements
+ else:
+ available = False
return available and boolean.true or boolean.false
- Previous message: [4suite-checkins] In 4Suite/Ft/Xml/XPath, files MessageSource.py,
ParsedExpr.py
- Next message: [4suite-checkins]
In 4Suite/Ft/Xml/Xslt/src, files stylesheet_tree.c,
xsltelement.c, xsltelement.h, xsltnode.c, xsltnode.h,
xsltroot.c, xsltroot.h, xslttext.c, xslttext.h
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the 4suite-checkins
mailing list