StylesheetTree.py :  » XML » 4Suite » 4Suite-XML-1.0.2 » Ft » Xml » Xslt » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » XML » 4Suite 
4Suite » 4Suite XML 1.0.2 » Ft » Xml » Xslt » StylesheetTree.py
########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/StylesheetTree.py,v 1.23 2005/05/11 16:11:05 jkloth Exp $
"""
Node classes for the stylesheet tree

Copyright 2004 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

class XsltNode:

    # positional information (for debugger and errors)
    # baseUri also used to set base URI of rtf nodes
    baseUri = ''
    lineNumber = '??'
    columnNumber = '??'
    importIndex = -1

    root = None
    parent = None
    expandedName = (None, None)
    nodeName = None
    children = None
    attributes = None

    # hints for performance
    doesSetup = False
    doesPrime = False
    doesIdle = False

    def isLastChild(self):
        siblings = self.parent.children
        if siblings.index(self) == len(siblings) - 1:
            return 1
        else:
            isLast = 1
            for node in siblings[siblings.index(self)+1:]:
                if not node.isPseudoNode():
                    isLast = 0
                    break
            return isLast

    def setup(self):
        return

    def prime(self, processor, context):
        return

    def idle(self, processor):
        return

    def instantiate(self, context, processor):
        return

    def isPseudoNode(self):
        return False

    def pprint(self, _indent=''):
        print _indent + str(self)
        if self.children:
            _indent += '  '
            for child in self.children:
                child.pprint(_indent)
        return


class XsltRoot(XsltNode):

    content = ContentInfo.Alt(ContentInfo.QName(XSL_NAMESPACE, 'xsl:stylesheet'),
                              ContentInfo.QName(XSL_NAMESPACE, 'xsl:transform'),
                              ContentInfo.ResultElements)

    validator = ContentInfo.Validator(content)

    nodeName = u'#document'

    def __init__(self, baseUri):
        self.root = self
        self.baseUri = baseUri
        # cache of original stylesheet source docs, keyed by URI
        self.sources = {}      # XML strings
        self.sourceNodes = {}  # Domlette documents
        # Regarding the cache:
        #
        # XSLT's document() function requires that the original stylesheet
        # documents be accessible as separate source document trees, but the
        # point of StylesheetReader is to avoid creating a Domlette document
        # for each stylesheet while building a single, compact stylesheet tree
        # (using the classes in this module) via the fastest parsing method
        # available. In order to support document(), we have to make it
        # possible to create, as needed, a Domlette document for each original
        # stylesheet, just in case somewhere in the stylesheet tree a
        # document() call or extension function makes reference to one of
        # those original documents. document('') is the most common case, but
        # not the only one.
        #
        # For now, we cache the original bytes of the document entity in the
        # stylesheet tree's XsltRoot object, and implement document() such
        # that it looks for documents in the Domlette cache in the XsltContext
        # first, then tries the cache we set up here, before falling back on
        # the normal resolver to fetch fresh content. If the doc is found in
        # our cache, then it is parsed and the Domlette is stored in the
        # XsltContext for future access. See XsltFunctions.py.
        #
        # Future optimization ideas:
        #  - After the stylesheet tree is built, look for document() calls
        #    in the XPath expressions, and if they all use single arguments
        #    that are hard-coded URI refs, resolve the refs to absolute form,
        #    and discard any cached docs that aren't in the resulting list.
        #  - Compress the cached strings, and decompress on the fly.
        #
        # FIXME: The cache does not include external entities or XIncludes;
        # they are refetched each time the cached document entity is read.
        # It is rare for a stylesheet to use ext. entities/XIncludes, though.
        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
        self.stylesheet = child
        self.children = [child]
        return

    def __str__(self):
        return "<XsltRoot at 0x%x>" % id(self)


# implements default behaviour for extension elements
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):
        self.root = root
        self.baseUri = baseUri
        self.expandedName = (namespaceUri, localName)
        self.children = []
        self.attributes = {}
        self.namespaces = {}
        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 instantiate(self, context, processor):
        """
        Implements default behavior of instantiating each child in the order
        that they appear in the stylesheet.
        """
        context.processorNss = self.namespaces
        context.currentInstruction = self

        for child in self.children:
            child.instantiate(context, processor)
        return

    def processChildren(self, context, processor):
        """
        Iterates over the children, instantiating them in the order that they
        appear in the stylesheet.
        """
        context.processorNss = self.namespaces
        context.currentInstruction = self

        for child in self.children:
            child.instantiate(context, processor)
        return

    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)


class XsltText(XsltNode):

    nodeName = u'#text'

    def __init__(self, root, baseUri, data):
        self.root = root
        self.baseUri = baseUri
        self.data = data
        return

    def instantiate(self, context, processor):
        processor.writers[-1].text(self.data)
        return

    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))
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.