Viewing file: __init__.py (7.4 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/__init__.py,v 1.30 2005/04/03 04:14:16 jkloth Exp $ """ 4XSLT initialization and XSLT pattern tools
Copyright 2003 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
# the order of imports here is very important
XSL_NAMESPACE = u'http://www.w3.org/1999/XSL/Transform'
import MessageSource Error = MessageSource.Error
# -- XSLT exceptions -------------------------------------------------
from Ft import FtException class XsltException(FtException): def __init__(self, errorCode, *args): FtException.__init__(self, errorCode, MessageSource.g_errorMessages, args) return
class XsltParserException(XsltException): """ The exception raised when an error is encountered during the parsing of a stylesheet. This eliminates the need for location information within each error message. """ def __init__(self, code, locator, *args): XsltException.__init__(self, code, *args)
# Add location information to the message msg = MessageSource.POSITION_INFO % (locator.getSystemId(), locator.getLineNumber(), locator.getColumnNumber(), self.message) self.message = msg return
class XsltRuntimeException(XsltException): def __init__(self, code, xsltelement, *args): XsltException.__init__(self, code, *args)
# Add location information to the message baseUri = xsltelement.baseUri or '?' line = xsltelement.lineNumber or '?' col = xsltelement.columnNumber or '?' msg = MessageSource.POSITION_INFO % (baseUri, line, col, self.message) self.message = msg return
# -- element classifications -----------------------------------------
class CategoryTypes: """Collection of constants making up the categories of XSLT element""" INSTRUCTION = 0 TOP_LEVEL_ELEMENT = 1 RESULT_ELEMENT = 2
import XPatternParserc as XPatternParser parser = XPatternParser
# -- XPattern API ----------------------------------------------------
from xml.dom import Node class PatternList: """ PatternList is a class that is useful for people writing code to process XSLT patterns, especially in groups. """ PARSER = parser.new() def __init__(self, patterns, namespaces=None): """ patterns - A list of strings that make up either compiled pattern objects or valid XSLT patterns in string form. It must be either all of one form or all of another namespaces - A namespace dictionary - { prefix: uri, ... } - to be used for setting up expressions in the pattern """ self.namespaces = namespaces or {} if hasattr(patterns[0], "match"): self._patterns = patterns else: self._patterns = [ self.PARSER.parse(p) for p in patterns ] self._shortcuts = [ p.getShortcuts(self.namespaces) for p in self._patterns ] self._lookup_table = {} self._patternMapping = {} i = 0 for shortcut_list in self._shortcuts: for ((subpattern, axis_type), (node_type, expanded_name)) in shortcut_list: self._patternMapping[subpattern] = self._patterns[i] if node_type == Node.ELEMENT_NODE: if not self._lookup_table.has_key(node_type): self._lookup_table[node_type] = {} if not self._lookup_table[node_type].has_key(expanded_name): self._lookup_table[node_type][expanded_name] = [] self._lookup_table[node_type][expanded_name].append((subpattern, axis_type, self._patterns[i])) else: if not self._lookup_table.has_key(node_type): self._lookup_table[node_type] = [] self._lookup_table[node_type].append((subpattern, axis_type, self._patterns[i])) i = i + 1 self.length = len(self._patterns) return
#def matchAll(nodes): # """Returns the subset of given nodes that match all patterns""" # return [ n for n in nodes if [ ] # ]
def lookup(self, node, context=None): """Return the patterns that match the node (as a list)""" if node.nodeType == Node.ELEMENT_NODE: #lookup result is a dict for elements narrowed_namecheck = self._lookup_table.get(Node.ELEMENT_NODE, {}) narrowed = narrowed_namecheck.get((node.namespaceURI, node.localName), []) #lookup of (ns,local) None is for the element wildcard case '*' narrowed.extend(narrowed_namecheck.get(None, [])) else: #lookup result is a list for non-elements narrowed = self._lookup_table.get(node.nodeType, []) if node.nodeType not in [ Node.DOCUMENT_NODE, Node.ATTRIBUTE_NODE ]: #lookup of nodeType None is for the wildcard case 'node()' narrowed.extend(self._lookup_table.get(None, [])) if not narrowed: return [] if not context: from Ft.Xml.XPath.Context import Context context = Context(node.ownerDocument, 1, 1, processorNss=self.namespaces) return [ p[2] for p in narrowed if p[0].match(context, node, p[1]) ]
def lookupAsSet(self, node, context=None): """Returns the patterns that match the node (as a set [dictionary])""" if node.nodeType == Node.ELEMENT_NODE: #lookup result is a dict for elements narrowed_namecheck = self._lookup_table.get(Node.ELEMENT_NODE, {}) narrowed = narrowed_namecheck.get((node.namespaceURI, node.localName), []) #lookup of (ns,local) None is for the element wildcard case '*' narrowed.extend(narrowed_namecheck.get(None, [])) else: #lookup result is a list for non-elements narrowed = self._lookup_table.get(node.nodeType, []) if node.nodeType not in [ Node.DOCUMENT_NODE, Node.ATTRIBUTE_NODE ]: #lookup of nodeType None is for the wildcard case 'node()' narrowed.extend(self._lookup_table.get(None, [])) if not narrowed: return {} matched_patterns = {} if not context: context = Context(node.ownerDocument, 1, 1) for p in narrowed: if p[0].match(context, node, p[1]): matched_patterns[p[2]] = None return matched_patterns
def xsltKeyPrep(self, context, node): """ A special utility used for XSLT key preparation. A list of lists is returned. The outer list corresponds to the patterns. Each inner list is either [node] or [] depending on whether or not the node matched the corresponding pattern. """ matching_patterns = self.lookupAsSet(node, context) return [ [node]*matching_patterns.has_key(p) for p in self._patterns ] #return [ [node]*(s[1][0] == node.nodeType and (s[1][0] != Node.ELEMENT_NODE or s[1][1] == (node.namespaceURI, node.localName)) and s[0][0].match(context, node)) for s in self._shortcuts ]
# this import must come after all the above from StylesheetTree import XsltElement
|