[zopeorg-checkins] CVS: Products/ParsedXML - AdaptableStorage.py:1.1 CHANGES.txt:1.1 CREDITS.txt:1.1 DOMProxy.py:1.1 Example.zexp:1.1 ExtraDOM.py:1.1 INSTALL.txt:1.1 LICENSE.Fourthought:1.1 LICENSE.txt:1.1 ManageableDOM.py:1.1 ParsedXML.py:1.1 PrettyPrinter.py:1.1 Printer.py:1.1 README.DOMProxy:1.1 README.parseprint:1.1 README.txt:1.1 StrIO.py:1.1 TransPubDOMProxy.py:1.1 __init__.py:1.1 main.dtml:1.1 version.txt:1.1

Sidnei da Silva sidnei at x3ng.com.br
Fri May 30 11:17:28 EDT 2003


Update of /cvs-zopeorg/Products/ParsedXML
In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML

Added Files:
	AdaptableStorage.py CHANGES.txt CREDITS.txt DOMProxy.py 
	Example.zexp ExtraDOM.py INSTALL.txt LICENSE.Fourthought 
	LICENSE.txt ManageableDOM.py ParsedXML.py PrettyPrinter.py 
	Printer.py README.DOMProxy README.parseprint README.txt 
	StrIO.py TransPubDOMProxy.py __init__.py main.dtml version.txt 
Log Message:
Adding products needed for migration of NZO

=== Added File Products/ParsedXML/AdaptableStorage.py ===
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Serializers for Shane's AdaptableStorage

    The properties must be deserialized prior the actual xml.

$Id: AdaptableStorage.py,v 1.1 2003/05/30 15:17:26 sidnei Exp $
"""
from types import StringType
from cStringIO import StringIO

from Products.AdaptableStorage.mapper.public import IAspectSerializer,\
    FieldSchema, RowSequenceSchema
from ParsedXML import ParsedXML, createDOMDocument

class ParsedXMLSerializer:
    """Serializer for ParsedXML Documents.

        Only the raw XML is stored in the filesystem.
    """
    
    __implements__ = IAspectSerializer

    schema = FieldSchema('data', 'string')
    attributes = (
           )
        
    def getSchema(self):
        return self.schema

    def canSerialize(self, object):
        return isinstance(object, ParsedXML)
    
    def serialize(self, object, event):
        encoding = 'utf-8'
        data = object.writeStream(encoding=encoding).getvalue().encode(encoding)
        event.ignoreAttributes([ '_node', '_persistentDoc', '_lenCache',
            '_lenCorrect', '_container'])
        return data

    def deserialize(self, object, event, state):
        assert isinstance(state, StringType)
        object._persistentDoc = object
        object._lenCache = 0
        object._lenCorrect = 0
        object.initFromDOMDocument(createDOMDocument(state, 
            not object.noNamespaces))


class ParsedXMLPropertiesSerializer:
    """Serialize parsed xml's properties"""
    
    __implements__ = IAspectSerializer
    
    schema = RowSequenceSchema()
    schema.addField('id', 'string', 1)
    schema.addField('type', 'string')
    schema.addField('data', 'string')

    attributes = {
        'title': str,
        'contentType': str,
        'noNamespaces': int,
     }

    def getSchema(self):
        return self.schema

    def canSerialize(self, object):
        return isinstance(object, ParsedXML)

    def serialize(self, object, event):
        res = []
        for attribute, factory in self.attributes.items():
            if not hasattr(object, attribute):
                continue
            value = getattr(object, attribute)
            t = factory.__name__
            if value is None:
                if factory in (int, long):
                    value = 0
                else: 
                    value = ''
            value = str(value)
            event.ignoreAttribute(attribute)
            res.append((attribute, t, value))
        return res 

    def deserialize(self, object, event, state):
        for attribute, t, value in state:
            factory = self.attributes.get(attribute)
            if factory is None:
                continue
            value = factory(value)
            setattr(object, attribute, value)
            assert getattr(object, attribute) == value



=== Added File Products/ParsedXML/CHANGES.txt ===
ParsedXML changes

  ParsedXML 1.3.1

    Bugs Fixed

      - Bugfix/performance improvement. Do not rely on getPersistentDocument()
        but instead use acquisition parent. This fixes a memory leak
        triggered when doing 'document.documentElement', and also likely
        improves performance when accessing the DOM through the ManageableDOM
        wrappers.

      - The Zope Find tab should now not give an error anymore when searching
        with ids.

      - Use the One True Way to import expat now ('from xml.parsers
        import expat').
  
  ParsedXML 1.3.0

    Features

      - All element nodes now have a _element_id id. This id is guaranteed
        to be unique in the document, though which id an element has may
        change in a reparse.

      - NodePath system for creating various paths to nodes. This can
        be based on 'child' (child node index), 'element_id', or
        'robust', which is not very robust as yet in some ways, but
        should be resistent to quite a few changes to the document.

      - added pretty printing feature. A pretty print button renders
        the document in pretty printed form, but does not save this
        changed version (you can do so yourself).

    Bugs Fixed

      - Removed ParsedXML's Expat, introduced dependency on PyXML's 
        pyexpat instead (or just compile your own). This gets rid of
        lots of install hassles, especially on Windows. Just install
        PyXML.

      - An ongoing attempt to bring sanity to the unit test story.

      - Avoid XML-garbling bug in Printer by using PrettyPrinter.

      - various bugfixes in the DOM.

  ParsedXML 1.2.1

    Features
 
      - pyexpat.c is now in sync with Python's and PyXML's version.

  ParsedXML 1.2.0

    Bugs Fixed

      - Tests are now more conformant with Zope unit testing guidelines.

      - Should work with Python 2.1/Zope 2.4, but not all the way 
        there yet (parser segfault..)

      - new version of PyExpat

    Features

      - Access to DOM from Zope environment sped up by new DOMProxy
        implementation

  ParsedXML 1.1b1

    Bugs Fixed

      - Fixed an ExpatBuilder bug that caused a DOM reference to be
        leaked when parsing occured at the document.  There is still a
        leak for fragment parsing that we're looking into.

    Features

      - ZCatalog support added

      - ZCache support added

  ParsedXML 1.1a1

    Bugs Fixed

      - Version numbers make more sense :)

    Features

      - The value returned by get_size() is cached, which will often
        speed up the management view of an instance's container. 

  ParsedXML 1.0

    Bugs Fixed

      - Problems with Attr Node manipulation not being reflected by
        the getAttribute methods of their Elements and vice versa
        fixed.

      - Erroneous position information for parse error output on
        subnodes fixed.

      - Default attributes are noticed by the parser and printer, and
        the relevent DOM methods work.

    Features

      - ManageableDOM Nodes can find the persistent Document wrapper
        when it has been installed in a Zope ObjectManager.  This
        object, rather than a newly created ManageableDocument
        wrapper, is returned when available by OwnerDocument calls.
        This allows Zopish navigation and discovery out of the
        Document, helps shorten acquisition paths, and fixes some bugs
        with manipulation at the Document.

      - ManageableDOM's usage of namespaces for parsing is now
        optional and settable.

      - The DOM 2 Traversal interface has been fleshed out, although
        support for visiblity and roots is not complete.

  ParsedXML 0.1b3

    Bugs Fixed

      - Yet a few more DOM bugs fixed.

      - Fixed a distribution error that was causing build problems
        under Solaris.

  ParsedXML 0.1b2

    Bugs Fixed

      - Many bugs found and fixed as we hammered out new DOM tests,
        especially in namespace usage, attribute printing, and
        attribute children.

    Features

      - Several speedups throughout the code.

      - ManageableDOM refactored into several base classes to make
        extension easier.

 
     


=== Added File Products/ParsedXML/CREDITS.txt ===
Current Maintainer:
  Martijn Faassen <faassen at infrae.com>
  
The Zope Corporation Parsed XML team:
  Karl Anderson
  Fred Drake <fdrake at zope.com>
  Todd Corum
  Martijn Pieters <mj at zope.com>

External Contributor:
  Martijn Faassen <faassen at infrae.com>

Much test and implementation help was provided by
  Chris McDonough <chrism at zope.com>
  Shane Hathaway <shane at zope.com>
  Guido van Rossum <guido at python.org>

Parsed XML also contains code from versions of the original
XMLDocument, written by Amos Latteier and Fourthought Inc.

ParsedXML contains software derived from works by Fourthought Inc; see
LICENSE.Fourthought for their license.


=== Added File Products/ParsedXML/DOMProxy.py === (505/605 lines abridged)
import DOM
import xml.dom

from ComputedAttribute import ComputedAttribute

import string

_DOM_PROXY_FEATURES = ()

class DOMImplementationProxy:
    def __init__(self):
        self._domimplementation = DOM.theDOMImplementation

    def hasFeature(self, feature, version):
        feature = string.lower(feature)
        if (feature, version) in _DOM_PROXY_FEATURES:
            return 1
        return self._domimplementation.hasFeature(feature, version)

    def _createDOMDocumentType(self, qualifiedName, publicId, systemId):
        return self._domimplementation.createDocumentType(
            qualifiedName, publicId, systemId)

    def _createDOMDocument(self, namespaceURI, qualifiedName, docType=None):
        return self._domimplementation.createDocument(
            namespaceURI, qualifiedName, docType)

class DOMProxy:

    def __init__(self, node, persistentDoc=None):
        self._node = node
        self._persistentDoc = persistentDoc
        
    def getDOMObj(self):
        """Return the node without wrappers.
        """
        return self._node
    
    def getPersistentDoc(self):
        """Return a reference to a security friendly persistent document
        if we can, or None.  This can be None when OwnerDocument, if it
        exsists, is not None.  If you don't need to reach the document
        through the security checks, you don't need to use this method.
        """    
        # We do this because the userfolder container needs to be in the aq
        # context of the unwrapped returned object.
        if self._persistentDoc and getattr(
            self._persistentDoc, "_container", None):
            
            try:

[-=- -=- -=- 505 lines omitted -=- -=- -=-]

class EntityReferenceProxy(NodeProxy):
    pass

class NotationProxy(NodeProxy):
    _DOMAttrs = NodeProxy._DOMAttrs + ("publicId", "systemId")

    def _get_publicId(self):
        return self._node._get_publicId()

    publicId = ComputedAttribute(_get_publicId)

    def _get_systemId(self):
        return self._node._get_systemId()

    systemId = ComputedAttribute(_get_systemId)
    
class DocumentTypeProxy(NodeProxy):
    _DOMAttrs = NodeProxy._DOMAttrs + ("publicId", "systemId",
                                       "name", "entities", "notations",
                                       "internalSubset")
    def _get_entities(self):
        return self.wrapNamedNodeMap(self._node._get_entities())

    entities = ComputedAttribute(_get_entities)
    
    def _get_internalSubset(self):
        return self._node._get_internalSubset()

    internalSubset = ComputedAttribute(_get_internalSubset)
    
    def _get_name(self):
        return self._node._get_name()

    name = ComputedAttribute(_get_name)
    
    def _get_notations(self):
        return self.wrapNamedNodeMap(self._node._get_notations())

    notations = ComputedAttribute(_get_notations)
    
    def _get_publicId(self):
        return self._node._get_publicId()

    publicId = ComputedAttribute(_get_publicId)
    
    def _get_systemId(self):
        return self._node._get_systemId()

    systemId = ComputedAttribute(_get_systemId)
    


=== Added File Products/ParsedXML/Example.zexp ===
ZEXP              ((U
OFS.FolderqUFolderqtqNt.}q(UidqUExampleqUtreeq(U      ¶q(hUFolderq	ttQU_objectsq
(}q(U	meta_typeqUFolderq
UidqUslidequ}q(hh
hUtreequtU__ac_local_roles__q}qUkarlq]qUOwnerqasUtitleqU h(U      q(hUFolderqttQU_ownerq(]qU	acl_usersqahtu.      ¶      Q((U
OFS.FolderqUFolderqtqNt.}q(UtitleqU UidqUtreeqUtreeq(U      q	(UOFS.DTMLDocumentq
UDTMLDocumentqttQU_objectsq(}q
(U	meta_typeqU
DTML DocumentqUidqUtreequ}q(hU
Parsed XMLqhUTreequtqUTreeq(U      »q(UProducts.ParsedXML.ParsedXMLqU	ParsedXMLqttQU__ac_local_roles__q}qUkarlq]qUOwnerqasu.            6((U
OFS.FolderqUFolderqtqNt.}q(U	nextSlideq(U      ±q(U#Products.PythonScripts.PythonScriptqUPythonScriptqttQUidq	Uslideq
U__ac_local_roles__q}qUkarlq
]qUOwnerqasU_objectsq(}q(U	meta_typeqU
DTML Documentqh	Uslidequ}q(U	meta_typeqU
Parsed XMLqUidqUSlidesqu}q(U	meta_typeqUDTML MethodqUidqU	viewSlidequ}q(U	meta_typeq UScript (Python)q!Uidq"hu}q#(h h!h"U
previousSlideq$u}q%(h h!h"UdomURLq&u}q'(h h!h"UgetColorq(utq)h(U      q*(UOFS.DTMLDocumentq+UDTMLDocumentq,ttQU_ownerq-(]q.U	acl_usersq/aUkarlq0tq1USlidesq2(U       q3(UProducts.ParsedXML.ParsedXMLq4U	ParsedXMLq5ttQU	viewSlideq6(U      ®q7(UOFS.DTMLMethodq8U
DTMLMethodq9ttQh((U      µq:(hUPythonScriptq;ttQUtitleq<U h$(U      ²q=(hUPythonScriptq>ttQUdomURLq?(U      ´q@(hUPythonScriptqAttQu.            à((UOFS.DTMLDocumentqUDTMLDocumentqtqNt.}q(UtitleqU
tree tag demoqUrawqT)  <dtml-var standard_html_header>
<h2><dtml-var title_or_id></h2>

<p>
The dtml-tree tag will show the ParsedXML DOM tree.
We use it in the DOM tree view, too.
</p>

<dtml-tree expr="Tree">
  <dtml-if "nodeType == 1">
   <dtml-var nodeName>
  </dtml-if>
</dtml-tree>

<dtml-var standard_html_footer>qU__ac_local_roles__q	}q
Ukarlq]qUOwnerq
asUglobalsq}qU__name__qUtreeqU_varsq}qu.      »      :((UProducts.ParsedXML.ParsedXMLqU	ParsedXMLqtqNt.}q(UidqUTreeqU_persistentDocq(U      »q(hU	ParsedXMLq	ttQU
_containerq
NU__ac_local_roles__q}qUkarlq
]qUOwnerqasUtitleqU UcontentTypeqUtext/xmlqUnoNamespacesqK U_nodeqcProducts.ParsedXML.DOM.Core
Document
qNRq}q(U	_childrenq]qcProducts.ParsedXML.DOM.Core
Element
qNRq}q(h]q(cProducts.ParsedXML.DOM.Core
Text
qNRq}q (U	nodeValueq!U

q"Udataq#h"ubhNRq$}q%(U	localNameq&Nh]q'(hNRq(}q)(h!U
  q*h#h*ubhNRq+}q,(h&Nh]q-(hNRq.}q/(h!U
    q0h#h0ubhNRq1}q2(UtagNameq3Uhairq4UnodeNameq5h4h&NUprefixq6NUnamespaceURIq7NubhNRq8}q9(h!U  
  q:h#h:ubeh3Uheadq;h5h;h6Nh7NubhNRq<}q=(h!U
  q>h#h>ubhNRq?}q@(h3UbodyqAh5hAh&Nh6Nh7NubhNRqB}qC(h!U
  qDh#hDubhNRqE}qF(h&Nh]qG(hNRqH}qI(h!U
    qJh#hJubhNRqK}qL(h3UtoesqMh5hMh&Nh6Nh7NubhNRqN}qO(h!U
  qPh#hPubeh3UfeetqQh5hQh6Nh7NubhNRqR}qS(h!U
h#U
ubeh3UthingqTh5hTh6Nh7NubhNRqU}qV(h!U


qWh#hWubhNRqX}qY(h&Nh]qZ(hNRq[}q\(h!U
  q]h#h]ubhNRq^}q_(h3Ufirstq`h5h`h&Nh6Nh7NubhNRqa}qb(h!U
  qch#hcubhNRqd}qe(h&Nh]qf(hNRqg}qh(h!U
    qih#hiubhNRqj}qk(h3Uthirdqlh5hlh&Nh6Nh7NubhNRqm}qn(h!U
  qoh#houbeh3Usecondqph5hph6Nh7NubhNRqq}qr(h!U
h#U
ubeh3hTh5hTh6Nh7NubhNRqs}qt(h!U

quh#huubeh3Uthingsqvh5hvubaUvalueqwNU
_elem_infoqx}qyUversionqzU1.0q{U
_attr_infoq|}q}ubu.      ±      5((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U	func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq	(Unodeq
U
$loop_watcherqU$read_guardqU$write_guardq
U$guardqtUco_argcountqK ubUidqU	nextSlideqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKU‘t } | ƒ  t } t } t }  	 | t  ƒ i }  
 xL 
 |  oA  | |  ƒ i d j o  |  Sn 
 | |  ƒ i }  | ƒ  q: W t Sd  Sq(NUslideqtq(UcontextqUnextSiblingqUnodeqUnodeNameqUNoneqU
$loop_watcherq U$read_guardq!U$write_guardq"U$guardq#tq$(hh h!h"h#tq%UScript (Python)q&hKU 
q')tN}q(tq)U_bodyq*T›  # return the next sibling with a nodeName of 'slide', or None.
# We need to do this because the parser doesn't treat whitespace text
# nodes specially; they're parsed into DOM text nodes just like
# everything else.

# Acquire this from the slide node that wants to find the next slide.

node = context.nextSibling
while node:
  if node.nodeName == 'slide':
    return node
  node = node.nextSibling
return Noneq+U_bind_namesq,(cShared.DC.Scripts.Bindings
NameAssignments
q-oq.}q/U_asgnsq0}q1(Uname_containerq2U	containerq3Uname_subpathq4Utraverse_subpathq5Uname_contextq6Ucontextq7Uname_m_selfq8Uscriptq9usbUPython_magicq:U™N
q;U
func_defaultsq<Nu.            "((UOFS.DTMLDocumentqUDTMLDocumentqtqNt.}q(UtitleqU
slide demoqUrawqTm  <dtml-var standard_html_header>
<H2><dtml-var title_or_id></H2>

<ol>
<dtml-in "Slides.documentElement.childNodes">
 <dtml-if "nodeName == 'slide'"> <!-- skip whitespace nodes -->
   <li>
    <a href="<dtml-var "domURL()">/viewSlide">
       <dtml-var "getAttribute('title')">
    </a>
   </li>
 </dtml-if nodeName>
</dtml-in>
</ol>

<dtml-var standard_html_footer>qU__ac_local_roles__q	}q
Ukarlq]qUOwnerq
asUglobalsq}qU__name__qUslideqU_varsq}qu.             Ã((UProducts.ParsedXML.ParsedXMLqU	ParsedXMLqtqNt.}q(UidqUSlidesqU_persistentDocq(U       q(hU	ParsedXMLq	ttQU
_containerq
NU__ac_local_roles__q}qUkarlq
]qUOwnerqasUtitleqU UcontentTypeqUtext/xmlqUnoNamespacesqK U_nodeqcProducts.ParsedXML.DOM.Core
Document
qNRq}q(U	_childrenq]qcProducts.ParsedXML.DOM.Core
Element
qNRq}q(U_attributesq]q]q(NUcolorq NNUgrayq!KeaUtagNameq"Uslidesq#UnodeNameq$h#h]q%(cProducts.ParsedXML.DOM.Core
Text
q&NRq'}q((U	nodeValueq)U
  q*Udataq+h*ubhNRq,}q-(h]q.]q/(NUtitleq0NNUfirst slideq1KeaU	localNameq2Nh]q3(h&NRq4}q5(h)U
    q6h+h6ubhNRq7}q8(h2Nh]q9h&NRq:}q;(h)U
    This is the first slide

    Here are some points,
    that I want to make:

      * one thing

      * another thing
    q<h+h<ubah"Ubodyq=h$h=Uprefixq>NUnamespaceURIq?Nubh&NRq@}qA(h)U
  qBh+hBubeh"UslideqCh$hCh>Nh?Nubh&NRqD}qE(h)U
  
  qFh+hFubhNRqG}qH(h]qI]qJ(Nh0NNUsecond slideqKKeah2Nh]qL(h&NRqM}qN(h)U
    qOh+hOubhNRqP}qQ(h2Nh]qRh&NRqS}qT(h)U˜
    This is the second slide

    Here are some points,
    that I want to make:

      1. one thing

      2. another thing

      3. final point
    qUh+hUubah"h=h$h=h>Nh?Nubh&NRqV}qW(h)U
  qXh+hXubeh"hCh$hCh>Nh?Nubh&NRqY}qZ(h)U
  
  q[h+h[ubhNRq\}q](h]q^(]q_(Nh0NNU
the red slideq`Ke]qa(Nh NNUredqbKeeh2Nh]qc(h&NRqd}qe(h)U
    qfh+hfubhNRqg}qh(h2Nh]qih&NRqj}qk(h)U¥
    This slide is red because it has a color
    attribute.

    All the others are gray because they didn't
    have a color attribute, but their parent did.

    qlh+hlubah"h=h$h=h>Nh?Nubh&NRqm}qn(h)U
  qoh+houbeh"hCh$hCh>Nh?Nubh&NRqp}qq(h)U   

qrh+hrubeubaUvalueqsNU
_elem_infoqt}quUversionqvU1.0qwU
_attr_infoqx}qyubu.      ®      Ã((UOFS.DTMLMethodqU
DTMLMethodqtqNt.}q(UtitleqU UrawqT  <dtml-var standard_html_header>

<dtml-let color="'red'"><!-- XXX replace -->

<table bgcolor='<dtml-var "getColor()">' border="1">
<tr><td>

<H2><dtml-var "getAttribute('title')"></H2>

<p>
<dtml-in childNodes>
 <dtml-if "nodeName == 'body'">
  <dtml-var "firstChild.data" fmt="structured-text">
 </dtml-if>
</dtml-in>    
</p>

</td></tr>
</table>

<dtml-if "nextSlide()">
 <dtml-with "nextSlide()">
  next:
  <a href="<dtml-var "domURL()">/viewSlide">
     <dtml-var "getAttribute('title')">
  </a>
 </dtml-with>
</dtml-if>

<dtml-if "previousSlide()">
 <dtml-with "previousSlide()">
  previous:
  <a href="<dtml-var "domURL()">/viewSlide">
     <dtml-var "getAttribute('title')">
  </a>
 </dtml-with>
</dtml-if>

</dtml-let color="red"><!-- XXX replace -->

<dtml-var standard_html_footer>
qU__ac_local_roles__q}q	Ukarlq
]qUOwnerqasUglobalsq
}qU__name__qU	viewSlideqU_varsq}qu.      µ      {((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U	func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq	(Unodeq
U
$loop_watcherqU$read_guardqU$write_guardq
U$guardqtUco_argcountqK ubUidqUgetColorqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKU—t } | ƒ  t } t } t	 }   t  }   x[  |  oP  | |  ƒ i d ƒ o  | |  ƒ i d ƒ Sn  | |  ƒ i }  | ƒ  q1 W	 t Sd  Sq(NUcolorqtq(UcontextqUnodeqUhasAttributeqUgetAttributeqU
parentNodeqUNoneq U
$loop_watcherq!U$read_guardq"U$write_guardq#U$guardq$tq%(hh!h"h#h$tq&UScript (Python)q'hKU	 
q()tN}q)tq*U_bodyq+UÌ# return a color attribute value from context or ancestors, or None.

node = context
while node:
  if node.hasAttribute('color'):
    return node.getAttribute('color')
  node = node.parentNode
return Noneq,U_bind_namesq-(cShared.DC.Scripts.Bindings
NameAssignments
q.oq/}q0U_asgnsq1}q2(Uname_containerq3U	containerq4Uname_subpathq5Utraverse_subpathq6Uname_contextq7Ucontextq8Uname_m_selfq9Uscriptq:usbUPython_magicq;U™N
q<U
func_defaultsq=Nu.      ²      Á((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U	func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq	(Unodeq
U
$loop_watcherqU$read_guardqU$write_guardq
U$guardqtUco_argcountqK ubUidqU
previousSlideqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKU‘t } | ƒ  t } t } t }   | t  ƒ i }   xL  |  oA 	 | |  ƒ i d j o 
 |  Sn  | |  ƒ i }  | ƒ  q: W t Sd  Sq(NUslideqtq(UcontextqUpreviousSiblingqUnodeqUnodeNameqUNoneqU
$loop_watcherq U$read_guardq!U$write_guardq"U$guardq#tq$(hh h!h"h#tq%UScript (Python)q&hKU 
q')tN}q(tq)U_bodyq*T  # return the previous sibling with a nodeName of 'slide', or None.
# see nextSlide.

# Acquire this from the slide node that wants to find the next slide.

node = context.previousSibling
while node:
  if node.nodeName == 'slide':
    return node
  node = node.previousSibling
return Noneq+U_bind_namesq,(cShared.DC.Scripts.Bindings
NameAssignments
q-oq.}q/U_asgnsq0}q1(Uname_containerq2U	containerq3Uname_subpathq4Utraverse_subpathq5Uname_contextq6Ucontextq7Uname_m_selfq8Uscriptq9usbUPython_magicq:U™N
q;U
func_defaultsq<Nu.      ´      ¸((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U	func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq	(UURLstrq
UnodeqU
$loop_watcherqU$read_guardq
U$write_guardqU$guardqtUco_argcountqK ubUidqUdomURLqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKU¾t } | ƒ  t } t } t	 }   d }   t } 	 xy 	 | on 
 | | ƒ i o!  | | ƒ i ƒ  d |  }  n 
 | | ƒ i ƒ  d |  }   | | ƒ i } | ƒ  q: W |  Sd  Sq(NU U/tq(UURLstrqUcontextqUnodeqU
parentNodeqUtpURLqUabsolute_urlq U
$loop_watcherq!U$read_guardq"U$write_guardq#U$guardq$tq%(hhh!h"h#h$tq&UScript (Python)q'hKU		 

q()tN}q)tq*U_bodyq+TÌ  # Return the URL for a DOM node, assuming it is has a parent.
# This illustrates that we need methods for a node to return its URL,
# as well as better URLs than sibling ordinality.
# This won't work for Attr nodes, they aren't children.

URLstr = "" 
node = context
while node:
  if node.parentNode:
    URLstr = node.tpURL() + '/' + URLstr
  else: # we're at the document
    URLstr = node.absolute_url() + '/' + URLstr
  node = node.parentNode
return URLstrq,U_bind_namesq-(cShared.DC.Scripts.Bindings
NameAssignments
q.oq/}q0U_asgnsq1}q2(Uname_containerq3U	containerq4Uname_contextq5Ucontextq6Uname_subpathq7Utraverse_subpathq8Uname_nsq9U_Uname_m_selfq:Uscriptq;usbUPython_magicq<U™N
q=U
func_defaultsq>Nu.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

=== Added File Products/ParsedXML/ExtraDOM.py ===
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################
"""
Non-DOM helper functions useful when working with either of our DOM
implementations, but not specific to any instantiation.
"""

from xml.dom import Node

import DOM.ExpatBuilder
import PrettyPrinter
from StrIO import StringIO


def parseFile(node, file, namespaces = 1):
    """
    Parse XML file, replace node with the resulting tree,
    return replacement.
    Node must be in an existing DOM tree if not a Document.
    """
    if node.nodeType == Node.DOCUMENT_NODE:
        return DOM.ExpatBuilder.parse(file, namespaces)
    elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
        raise Exception, "replacing a document fragment doesn't make sense"
    else:
        fragment = DOM.ExpatBuilder.parseFragment(
            file, node.parentNode, namespaces)
        #if fragment.childNodes.length != 1:
        #    # we could do this, actually, if we wanted
        #    raise Exception, "replacing a Node with less or more " + \
        #          "than one tree of Nodes is not implemented"
        sib = node.nextSibling
        parent = node.parentNode
        parent.removeChild(node)
        #print fragment.childNodes.length
        #for child in fragment.childNodes:
        #    print child.nodeType, node.nodeName
        #    if child.nodeType == Node.TEXT_NODE:
        #        print repr(child.data) 
        return parent.insertBefore(fragment.firstChild, sib) # frag.firstChild
         

def writeStream(node, stream = None, encoding = None, html = 0,
                contentType = None, prettyPrint = 0):
    "Write the XML representation of node to stream."
    if stream is None:
        stream = StringIO()
    PrettyPrinter.PrintVisitor(node, stream, encoding, html,
                               contentType, prettyPrint=prettyPrint)()
    return stream

    


=== Added File Products/ParsedXML/INSTALL.txt ===
Requirements

  This release requires Zope 2.4.x and later. You also need PyXML
  0.7.x or later installed, or at least a recent version of pyexpat.

Installation

  Unpack the ParsedXML tarball in the Products directory of your Zope
  installation (usually this is lib/python/Products). Rename the unpacked
  directory to "ParsedXML" so that Python can import it.

  Restart Zope.  There should be a ParsedXML product in your Products
  folder, and a ParsedXML option for available objects to add in
  the root folder.



=== Added File Products/ParsedXML/LICENSE.Fourthought ===
Copyright (c) 2000 Fourthought Inc, USA

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of FourThought LLC not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

FOURTHOUGHT LLC DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
IN NO EVENT SHALL FOURTHOUGHT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.




=== Added File Products/ParsedXML/LICENSE.txt ===
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################


=== Added File Products/ParsedXML/ManageableDOM.py === (655/755 lines abridged)

#############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations

[-=- -=- -=- 655 lines omitted -=- -=- -=-]


    def _get_implementation(self):
        return self.implementation
    
    #block set of implementation, since we don't proxy it the same
    def __setattr__(self, name, value):
        if name == "implementation":
            raise xml.dom.NoModificationAllowedErr()
        ManageableDocument.inheritedAttribute('__setattr__')(self, name, value)

# DOM extended interfaces

class ManageableEntityReference(ManageableWrapper,
                                DOMProxy.EntityReferenceProxy,
                                ManageableNode):
    "A wrapper around a DOM EntityReference."
    meta_type = "Manageable Entity Reference"

class ManageableEntity(ManageableWrapper, DOMProxy.EntityProxy,
                       ManageableNode):
    "A wrapper around a DOM Entity."
    meta_type = "Manageable Entity"

class ManageableNotation(ManageableWrapper, DOMProxy.NotationProxy,
                         ManageableNode):
    "A wrapper around a DOM Notation."
    meta_type = "Manageable Notation"

class ManageableDocumentType(ManageableWrapper, DOMProxy.DocumentTypeProxy,
                             ManageableNode):
    "A wrapper around a DOM DocumentType."
    meta_type = "Manageable Document Type"    


Node = xml.dom.Node
WRAPPER_TYPES = {
    Node.ELEMENT_NODE: ManageableElement,
    Node.ATTRIBUTE_NODE: ManageableAttr,
    Node.TEXT_NODE: ManageableText,
    Node.CDATA_SECTION_NODE: ManageableCDATASection,
    Node.ENTITY_REFERENCE_NODE: ManageableEntityReference,
    Node.ENTITY_NODE: ManageableEntity,
    Node.PROCESSING_INSTRUCTION_NODE: ManageableProcessingInstruction,
    Node.COMMENT_NODE: ManageableComment,
    Node.DOCUMENT_NODE: ManageableDocument,
    Node.DOCUMENT_TYPE_NODE: ManageableDocumentType,
    Node.DOCUMENT_FRAGMENT_NODE: ManageableDocumentFragment,
    Node.NOTATION_NODE: ManageableNotation,
    }
del Node


=== Added File Products/ParsedXML/ParsedXML.py ===
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################
"""
Zope Product creation for Parsed XML.
"""

from OFS.SimpleItem import SimpleItem
from AccessControl.Role import RoleManager
from Persistence import Persistent
from Acquisition import Implicit
from OFS.Cache import Cacheable
import Globals

from ManageableDOM import ManageableDocument, DOMManageable, \
     theDOMImplementation
from StrIO import StringIO
from xml.parsers import expat
import DOM, ExtraDOM

from types import FileType, StringType
from urllib import quote

from NodePath import registry

_marker = []  # dummy default object for cache return

parserr=('Sorry, an XML parsing error occurred.  Check '
         'your XML document for well-formedness and try '
         'to upload it again after modification.<br><br>')

def manage_addParsedXML(self,id,title='',file='',
                        useNamespaces = 1, contentType = "text/xml",
                        REQUEST=None,submit=None):
    "Add a Parsed XML instance with optional file content."

    if not file or not isinstance(file, StringType):
        file ='<?xml version = "1.0"?><emptydocumentElement/>'
    try:
        ob = ParsedXML(id, file, useNamespaces, contentType)
    except expat.error, e:
        if REQUEST is not None:
            err = "%s%s" % (parserr, '<font color="red">%s</font>'
                            % getattr(e, 'args', ''))
            return Globals.MessageDialog(
                title= 'XML Parsing Error',
                message = err,
                action='manage_main')
        raise
    ob.title = str(title)
    id = self._setObject(id, ob)
    if REQUEST is not None:
        try: u=self.DestinationURL()
        except: u=REQUEST['URL1']
        if submit==" Add and Edit ": u="%s/%s" % (u,quote(id))
        REQUEST.RESPONSE.redirect(u+'/manage_main')


manage_addParsedXMLForm = Globals.DTMLFile('dtml/documentAdd', globals())


def createDOMDocument(XMLstring = None, namespaces = 1):
    "Helper function to create a DOM document, without any proxy wrappers."
    if XMLstring:
        XMLstring=StringIO(XMLstring)
        # more efficient to not use ExtraDOM here
        return DOM.ExpatBuilder.parse(XMLstring, namespaces)
    # we use DOM.theDOMImplementation, not ManageableDOMs, for efficiency
    return DOM.theDOMImplementation.createDocument(
        None, "mydocument", None)

contentTypes = ['text/html', 'application/html', 'text/xml']
    
class ParsedXML(SimpleItem, ManageableDocument, Cacheable):
    "The Parsed XML top object, and the persistent head of the tree."
     
    meta_type = 'Parsed XML'

    manage_editForm = Globals.HTMLFile('dtml/persEdit',globals())
    
    manage_options = (DOMManageable.manage_options +
                      RoleManager.manage_options +
                      Cacheable.manage_options)

    __ac_permissions__ = (('View management screens', ('manage_main',),
                           ('Manager',)),
                          ('View DOM hierarchy', ('manage_DOMTree',),
                           ('Manager',)),
                          ('Edit ParsedXML', ('manage_editForm',),
                           ('Manager',)),
                          ('View source', ('index_html',),
                           ('Manager',)),
                          ('Access contents information',
                           ('objectIds', 'objectValues', 'objectItems',
                            ''),
                           ('Manager',)),)

    icon = 'misc_/ParsedXML/pxml.gif'

    def __init__(self, id, XMLstring = None, namespaces = 1,
                 contentType = "text/xml"):
        "Initialize a Parsed XML object"
        self.id = id
        self._persistentDoc = self # used by transient proxies
        self.noNamespaces = not namespaces
        if contentType not in contentTypes:
            import string
            raise RuntimeError, (
                "Bad content type %s; valid types are %s"
                % (str(contentType), string.join(contentTypes)))
        self.contentType = contentType
        self.initFromDOMDocument(createDOMDocument(XMLstring, namespaces))
        if XMLstring:
            self._lenCache = len(XMLstring)
        else:
            self._lenCache = len(str(self))
        self._lenCorrect = 1

    initFromDOMDocument__roles__ = ()  # Private
    def initFromDOMDocument(self, DOMdoc):
        "Initialize a Parsed XML from a DOM Document"
        # inherit from ManageableDocument
        ParsedXML.inheritedAttribute('__init__')(self, DOMdoc, self)

    def manage_afterAdd(self, object, container):
        """Store the container that we're being added to.  This is used
        to traverse back to the persistent document."""
        self._container = container

    #
    # methods that deal with persistence
    #

    # DOM nodes use __changed__ because its acquirable
    # Setting _p_changed is equivalent.
    def __changed__(self, *args):
        """Override the acquired __changed__ method used by the non-DB
        DOM nodes, update length cache, and mark this object as dirty."""
        if getattr(self, '_v_lenCorrect', None):
            self._lenCorrect = 1
        else:
            self._lenCorrect = 0
        self.ZCacheable_invalidate()            
        self._p_changed = 1

    # wrap DOMIO to provide cacheing
    def index_html(self, REQUEST = None, RESPONSE = None):
        "Returns publishable source according to content type"
        if RESPONSE:
            RESPONSE.setHeader('Content-type', self.contentType)
        data = self.ZCacheable_get(default = _marker)
        if data is not _marker:
            return data
        # inherit from DOMIO
        data = ParsedXML.inheritedAttribute('index_html')(self,
                                                          REQUEST, RESPONSE)
        self.ZCacheable_set(data)
        return data
    
    def get_size(self):
        "Length of the XML string representing this node in characters."
        if not getattr(self, '_lenCorrect', 0):
            self._lenCache = len(str(self))
            self._lenCorrect = 1
        return self._lenCache

    # methods that override ZDOM methods that are incorrect
    #
    
    def getElementsByTagName(self, tagName):
        return self.__getattr__("getElementsByTagName")(tagName)

    def hasChildNodes(self):
        return self.__getattr__("hasChildNodes")()

    # 
    # methods that override SimpleItem; sigh, multiple inheritance.
    #

    def objectValues(self, spec=None):
        """
        Returns a list of actual subobjects of the current object.
        If 'spec' is specified, returns only objects whose meta_type
        match 'spec'.
        """
        return ManageableDocument.objectValues(self, spec)
    
    def objectIds(self, spec=None):
        """
        Returns a list of subobject ids of the current object.
        If 'spec' is specified, returns objects whose meta_type
        matches 'spec'.
        """
        return ManageableDocument.objectIds(self, spec)

    def objectItems(self, spec=None):
        """
        Returns a list of (id, subobject) tuples of the current object.
        If 'spec' is specified, returns only objects whose meta_type match
        'spec'
        """
        return ManageableDocument.objectItems(self, spec)
    
    def tpValues(self):
        "Return a list of immediate subobjects.  Used by the dtml-tree tag."
        return ManageableDocument.tpValues(self)

    # override ManageableDocument's method; we can't persist new DOM node by
    # hanging off of parents
    def parseXML(self, file):
        "parse file as XML, replace DOM node with resulting tree, return self"
        namespaces = not self.noNamespaces
        node = ExtraDOM.parseFile(self.getDOMObj(), file, namespaces)
        self.initFromDOMDocument(node)
        self.__changed__(1)
        return self

    def getDOM(self):
        """Get the Document node of the DOM tree.
        """
        return self

    def getNodePath(self, scheme_name, node):
        """Create the node path for a particular node in the tree.
        """
        # if we're asking for node of this document itself
        if node is self:
            return 'scheme_name'
        # otherwise ask for nodepath of node
        return node.getNodePath(scheme_name)
        
    def resolveNodePath(self, path):
        """Resolve node path from top of the tree to node.
        """
        # start resolving from the document node
        doc = self._persistentDoc._earlyAqChain()
        # FIXME: could use raw DOM instead of management wrappers
        return registry.resolve_path(doc, path)
        
    def __getitem__(self, s):
        """Handle node paths.
        """
        # backwards compatibility -- handle classic 0/1/2 paths
        try:
            return self.childNodes[int(s)].__of__(self)
        except ValueError:
            pass
        
        # start resolving from the document node
        doc = self._persistentDoc._earlyAqChain()
        # FIXME: could use raw DOM instead of management wrappers
        result = registry.resolve_path(doc, s)
        # FIXME: does this convince ZPublisher to show NotFound?
        if result is None:
            raise KeyError, "Could not resolve node path."
        return result
    
Globals.default__class_init__(ParsedXML) # activate perms


=== Added File Products/ParsedXML/PrettyPrinter.py ===
import re
import string
from DOM.Core import Node, XMLNS_NS, XML_NS
import sys
from StrIO import StringIO

# an XML printer which:
#   * can do pretty printing, optionally
#   * as opposed to the one defined in Printer.py, actually should
#     be less buggy

class PrintVisitor:
    
    def __init__(self, root, stream=sys.stdout, encoding=None,
                 html=0, contentType=None, entityReferenceExpansion=1,
                 prettyPrint=0, indentLevel=2):
        self.namePrint = lambda s: s # identity
        if contentType and html:
            if contentType == 'html':
                self.namePrint = string.upper
            elif contentType == 'xml':
                self.namePrint = string.lower
        self.root = root
        self.stream = stream
        self.encoding = encoding
        self.html = html
        self.contentType = contentType
        self.entityReferenceExpansion = entityReferenceExpansion
        self.prettyPrint = prettyPrint
        self.indent = 0
        self.indentLevel = indentLevel
        
        self.nodeType2method = { 
            Node.ELEMENT_NODE: self.renderElement,
            Node.ATTRIBUTE_NODE: self.renderAttr,
            Node.TEXT_NODE: self.renderText,
            Node.CDATA_SECTION_NODE: self.renderCDATASection,
            Node.ENTITY_REFERENCE_NODE: self.renderEntityReference,
            Node.ENTITY_NODE: self.renderEntity,
            Node.PROCESSING_INSTRUCTION_NODE:\
            self.renderProcessingInstruction,
            Node.COMMENT_NODE: self.renderComment,
            Node.DOCUMENT_NODE: self.renderDocument,
            Node.DOCUMENT_TYPE_NODE: self.renderDocumentType,
            Node.DOCUMENT_FRAGMENT_NODE: self.renderDocumentFragment,
            Node.NOTATION_NODE: self.renderNotation,
        }

    def renderAll(self):
        return self.render(self.stream, self.root)

    __call__ = renderAll
    
    def render(self, f, node):
        self.nodeType2method[node.nodeType](f, node)
        
    def renderElement(self, f, node):
        if self.prettyPrint:
            f.write(" " * self.indent * self.indentLevel)
        f.write("<")
        f.write(self.namePrint(node.tagName))
        for attribute in node.attributes.values():
            self.renderAttr(f, attribute)
        if not node.hasChildNodes():
            if self.html:
                if node.tagName.upper() not in HTML_FORBIDDEN_END:
                    f.write('></')
                    f.write(self.namePrint(node.tagName))
                    f.write('>')
                else:
                    f.write(' />')
            else:
                f.write('/>')
            if self.prettyPrint:
                f.write("\n")
        else:
            f.write('>')
            prettyPrint = self.prettyPrint

            stream = f
            if prettyPrint:
                f.write("\n")                    
                no_indentation = 0
                for child in node.childNodes:
                    if (child.nodeType == Node.TEXT_NODE and
                        child.data.strip() != ''):
                        no_indentation = 1
                        break
                if no_indentation:
                    stream = StringIO()
                    self.prettyPrint = 0
                self.indent += 1
                
            for child in node.childNodes:
                self.render(stream, child)

            self.prettyPrint = prettyPrint
            
            if prettyPrint:
                if no_indentation:
                    f.write(indentBlock(
                        stream.getvalue().strip(),
                        self.indent * self.indentLevel, 70))
                    f.write('\n')
                self.indent -= 1
                
                f.write(" " * self.indent * self.indentLevel)
            f.write("</%s>" % self.namePrint(node.tagName))
            if self.prettyPrint:
                f.write("\n")

    def renderAttr(self, f, node):
        if not node.specified:
            return
        text, delimiter = _translateCdataAttr(node.value,
                                              encoding=self.encoding)
        f.write(" %s=%s%s%s" % (self.namePrint(node.name),
                                delimiter, text, delimiter))
        
    def renderText(self, f, node):
        data = node.data
        if self.prettyPrint:
            data = node.data.strip()
            if data == "":
                return
            data = indentBlock(data, self.indent * self.indentLevel, 70)
        f.write(_translateCdata(data, self.encoding))
        if self.prettyPrint:
            f.write('\n')
            
    def renderCDATASection(self, f, node):
        f.write("<![CDATA[")
        f.write(node.data.replace("]]>", "]]]><![CDATA[]>"))
        f.write("]]>")

    def renderEntityReference(self, f, node):
        f.write('&')
        f.write(node.nodeName)
        f.write(';')

    def renderEntity(self, f, node):
        st = "<!ENTITY " + node.nodeName
        if not node.systemId:
            # internal entity
            s = node.firstChild.data
            st = '%s "%s"' % (st, _translateCdata(s, self.encoding))
        if node.publicId:
            st = st + ' PUBLIC "%s"' % node.publicId
            if node.systemId:
                st = '%s "%s"' % (st, node.systemId)
        elif node.systemId:
            st = st + ' SYSTEM "%s"' % node.systemId
        if node.notationName:
            st = st + ' NDATA %s' % node.notationName
        f.write(st + '>\n')
    
    def renderProcessingInstruction(self, f, node):
        f.write('<?')
        f.write(node.target + ' ')
        f.write(node.data)
        f.write('?>')

    def renderComment(self, f, node):
        f.write('<!--')
        f.write(node.data)
        f.write('-->')

    def renderDocument(self, f, node):
        if not self.html:
            f.write('<?xml version="1.0"')
            if self.encoding:
                f.write(' encoding="%s"' % self.encoding)
            f.write(' ?>\n')
        for child in node.childNodes:
            self.render(f, child)
        f.write('\n')
        
    def renderDocumentType(self, f, node):
        if (not node.entities.length and
            not node.notations.length and
            not node.systemId):
            return

        f.write("<!DOCTYPE ")
        f.write(node.name)

        if node.systemId:
            if node.publicId:
                if '"' not in node.publicId:
                    f.write(' PUBLIC "' + node.publicId + '" ')
                else:
                    f.write(" PUBLIC '" + node.publicId + "' ")
            else:
                f.write(' SYSTEM ')

            if '"' not in node.systemId:
                f.write('"' + node.systemId + '"')
            else:
                f.write("'" + node.systemId + "'")

        if node.internalSubset:
            f.write(" [%s]" % node.internalSubset)
        elif node.entities.length or node.notations.length:
            f.write(' [\n')
            for i in range(node.entities.length):
                self.render(f, node.entities.item(i))
            for i in range(node.notations.length):
                self.render(f, node.notations.item(i))
            f.write(']')
        f.write('>\n')
       
    def renderNotation(self, f, node):
        st = "<!NOTATION %s" % node.nodeName
        if node.publicId:
            st = st + ' PUBLIC "%s"' % node.publicId
            if node.systemId:
                st = '%s "%s"' % (st, node.systemId)
        elif node.systemId:
            st = st + ' SYSTEM "%s"' % node.systemId
        f.write(st + '>\n')

    def renderDocumentFragment(self, f, node):
        for child in node.childNodes:
            self.render(f, child)
            
# regexps used by _translateCdata(),
# made global to compile once.
# see http://www.xml.com/axml/target.html#dt-character
ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]'
SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]'
ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]'
# Note: Prolly fuzzy on this, but it looks as if characters from the
# surrogate block are allowed if in scalar form, which is encoded in UTF8 the
# same was as in surrogate block form
XML_ILLEGAL_CHAR_PATTERN = re.compile(
    '%s|%s' % (ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS))
# the characters that we will want to turn into entrefs
# We must do so for &, <,  and > following ]].
# The xml parser has more leeway, but we're not the parser.
# http://www.xml.com/axml/target.html#dt-chardata
# characters that we must *always* turn to entrefs:
g_cdataCharPatternReq = re.compile('[&<]|]]>')
g_charToEntityReq = {
    '&': '&amp;',
    '<': '&lt;',
    ']]>': ']]&gt;',
    }
# characters that we must turn to entrefs in attr values:
g_cdataCharPattern = re.compile('[&<>"\']|]]>')
g_charToEntity = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&apos;',
    ']]>': ']]&gt;',
    }

# HTML nodes to always be minimzied, else never minimize
# from PyXML's xml.dom.html
# http://www.w3.org/TR/xhtml1/#guidelines
HTML_FORBIDDEN_END = ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME',
                      'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM']


def _translateCdata(characters, allEntRefs = None, encoding='UTF-8'):
    """Translate characters into a legal format."""
    if not characters:
        return ''
    if allEntRefs: # translate all chars to entrefs; for attr value
        if g_cdataCharPattern.search(characters):
            new_string = g_cdataCharPattern.subn(
                lambda m, d=g_charToEntity: d[m.group()],
                characters)[0]
        else:
            new_string = characters
    else: # translate only required chars to entrefs
        if g_cdataCharPatternReq.search(characters):
            new_string = g_cdataCharPatternReq.subn(
                lambda m, d=g_charToEntityReq: d[m.group()],
                characters)[0]
        else:
            new_string = characters
    if XML_ILLEGAL_CHAR_PATTERN.search(new_string):
        new_string = XML_ILLEGAL_CHAR_PATTERN.subn(
            lambda m: '&#%i;' % ord(m.group()),
            new_string)[0]
    #new_string = utf8_to_code(new_string, encoding) # XXX ugh
    return new_string

def _translateCdataAttr(characters, encoding='UTF-8'):
    """
    Translate attribute value characters into a legal format;
    return the value and the delimiter used.
    """
    if not characters:
        return '', '"'
    if '"' not in characters or "'" in characters:
        delimiter = '"'
        new_chars = _translateCdata(characters, allEntRefs = 1,
                                    encoding=encoding)
        new_chars = re.sub("&apos;", "'", new_chars)
    else:
        delimiter = "'"
        new_chars = _translateCdata(characters, allEntRefs = 1,
                                    encoding=encoding)            
        new_chars = re.sub("&quot;", '"', new_chars)
    return new_chars, delimiter

def indentBlock(text, indent, line_length):
    words = text.split()
    lines = []
    i = 0
    while i < len(words):
        line = []
        while i < len(words) and indent + len(" ".join(line)) < line_length:
            line.append(words[i])
            i += 1
        if len(line) > 1 and indent + len(" ".join(line)) >= line_length:
            i -= 1
            line.pop()
        lines.append(" " * indent + " ".join(line))
    return '\n'.join(lines)

    


=== Added File Products/ParsedXML/Printer.py ===
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################

#
# Specifically, most of this code is from PyXML's xml.dom.ext.Printer.
# See LICENSE.Fourthought.
#

"""
Printing and XML generating support for DOM classes.
"""
import re
import string

# regexps used by _translateCdata(),
# made global to compile once.
# see http://www.xml.com/axml/target.html#dt-character
ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]'
SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]'
ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]'
#Note: Prolly fuzzy on this, but it looks as if characters from the surrogate block are allowed if in scalar form, which is encoded in UTF8 the same was as in surrogate block form
XML_ILLEGAL_CHAR_PATTERN = re.compile('%s|%s'%(ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS))
# the characters that we will want to turn into entrefs
# We must do so for &, <,  and > following ]].
# The xml parser has more leeway, but we're not the parser.
# http://www.xml.com/axml/target.html#dt-chardata
# characters that we must *always* turn to entrefs:
g_cdataCharPatternReq = re.compile('[&<]|]]>')
g_charToEntityReq = {
        '&': '&amp;',
        '<': '&lt;',
        ']]>': ']]&gt;',
        }
# characters that we must turn to entrefs in attr values:
g_cdataCharPattern = re.compile('[&<>"\']|]]>')
g_charToEntity = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&apos;',
        ']]>': ']]&gt;',
        }

# HTML nodes to always be minimzied, else never minimize
# from PyXML's xml.dom.html
# http://www.w3.org/TR/xhtml1/#guidelines
HTML_FORBIDDEN_END = ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME',
                      'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM']

from DOM.Core import Node, XMLNS_NS, XML_NS
from DOM import Traversal
import sys

class Visitor:
    """A class to visit an entire tree according to a TreeWalker."""

    # These are both used for html mode.  These aren't the types that
    # the server returns; 'html' covers '*/html', etc.
    contentTypes = ['html', 'xml']
    
    def __init__(self, root, stream = sys.stdout, encoding = None,
                 html = 0, contentType = None,
                 whatToShow = Traversal.NodeFilter.SHOW_ALL,
                 filter = None, entityReferenceExpansion = 1):
        if root.ownerDocument:
            doc = root.ownerDocument
        else:
            doc = root
        self.tw = doc.createTreeWalker(root, whatToShow, filter,
                                       entityReferenceExpansion)
        self.stream = stream
        self.encoding = encoding
        self.html = html

        if contentType and contentType not in self.contentTypes:
            raise RuntimeError, (
                "Bad content type %s; valid types are 'html', 'xml'"
                % contentType)
        self.contentType = contentType

        # elt/attr names: html */html upcase, html */xml lowercase.
        # http://www.w3.org/TR/xhtml1/#guidelines        
        self.namePrint = lambda string: string # identity
        if self.contentType and self.html:
            if self.contentType == 'html':
                self.namePrint = string.upper
            elif self.contentType == 'xml':
                self.namePrint = string.lower

        # maps node type to visitor method
        self.NODE_TYPES = {
            Node.ELEMENT_NODE: self.visitElement,
            Node.ATTRIBUTE_NODE: self.visitAttr,
            Node.TEXT_NODE: self.visitText,
            Node.CDATA_SECTION_NODE: self.visitCDATASection,
            Node.ENTITY_REFERENCE_NODE: self.visitEntityReference,
            Node.ENTITY_NODE: self.visitEntity,
            Node.PROCESSING_INSTRUCTION_NODE: \
            self.visitProcessingInstruction,
            Node.COMMENT_NODE: self.visitComment,
            Node.DOCUMENT_NODE: self.visitDocument,
            Node.DOCUMENT_TYPE_NODE: self.visitDocumentType,
            Node.DOCUMENT_FRAGMENT_NODE: self.visitDocumentFragment,
            Node.NOTATION_NODE: self.visitNotation,
            }


    # methods to drive the walker

    def visitWhole(self):
        curNode = self.tw.currentNode
        self.visit(curNode, start = 1)
        self.visitChildren()
        self.visit(curNode, start = 0)        

    __call__ = visitWhole

    def visitChildren(self):
        if self.tw.firstChild():
            self.visitWhole()
            while (self.tw.nextSibling()):
                self.visitWhole()
            self.tw.parentNode()

    # methods that do stuff once we're there, without moving the walker        
    def visitElement(self, node, start):
        self.visitGeneric(node)
    def visitAttr(self, node, start):
        self.visitGeneric(node)
    def visitText(self, node, start):
        self.visitGeneric(node)
    def visitCDATASection(self, node, start):
        self.visitGeneric(node)
    def visitEntityReference(self, node, start):
        self.visitGeneric(node)
    def visitEntity(self, node, start):
        self.visitGeneric(node)
    def visitProcessingInstruction(self, node, start):
        self.visitGeneric(node)
    def visitComment(self, node, start):
        self.visitGeneric(node)
    def visitDocument(self, node, start):
        self.visitGeneric(node)
    def visitDocumentType(self, node, start):
        self.visitGeneric(node)
    def visitDocumentFragment(self, node, start):
        self.visitGeneric(node)
    def visitNotation(self, node, start):
        self.visitGeneric(node)

    def visitGeneric(self, node):
        self.stream.write("visit %s node %s\n"%(node.nodeType, node.nodeName))

    def visit(self, node, start):
        "Find the element type and call the appropriate visit method"
        visitMethod = self.NODE_TYPES.get(node.nodeType, None)
        if visitMethod is None:
            raise TypeError, (
                "Cannot print unknown nodeType: %s" % node.nodeType)
        else:
            return visitMethod(node, start)

# we'll want hooks to generalize this for prettyprinting etc:
# add formatting, named constants for < etc so we can &lt; etc.
class PrintVisitor(Visitor):
    """A class to generate XML for a tree according to a TreeWalker"""

    def visitElement(self, node, start):
        if start:
            self.stream.write('<' + self.namePrint(node.tagName))
            st = ''
            for item in node.attributes.values():
                self.visitAttr(item, start=1)
            if not node.hasChildNodes():
                if self.html:
                    if string.upper(node.tagName) not in HTML_FORBIDDEN_END:
                        self.stream.write('></' + self.namePrint(node.tagName)
                                          + '>')
                    else:
                        self.stream.write(' />')
                else:
                    self.stream.write('/>')
            else:
                self.stream.write('>')
        else:
            if node.hasChildNodes():
                self.stream.write('</' + self.namePrint(node.tagName) + '>')

    def visitAttr(self, node, start):
        if start and node.specified:
            text, delimiter = _translateCdataAttr(node.value)
            self.stream.write(" %s=%s%s%s" %
                              (self.namePrint(node.name), delimiter,
                               text, delimiter))

    def visitText(self, node, start):
        if start:
            self.stream.write(_translateCdata(node.data, self.encoding))

    def visitCDATASection(self, node, start):
        if start:
            self.stream.write('<![CDATA[')
            self.stream.write(string.replace(node.data,
                                             "]]>", "]]]><![CDATA[]>"))
            self.stream.write(']]>')

    def visitEntityReference(self, node, start):
        if start:
            self.stream.write('&')
            self.stream.write(node.nodeName)
            self.stream.write(';')

    def visitEntity(self, node, start):
        if start:
            st = "<!ENTITY " + node.nodeName
            if not node.systemId:
                # internal entity
                s = node.firstChild.data
                st = '%s "%s"' % (st, _translateCdata(s, self.encoding))
            if node.publicId:
                st = st + ' PUBLIC "%s"' % node.publicId
                if node.systemId:
                    st = '%s "%s"' % (st, node.systemId)
            elif node.systemId:
                st = st + ' SYSTEM "%s"' % node.systemId
            if node.notationName:
                st = st + ' NDATA %s' % node.notationName
            self.stream.write(st + '>\n')

    def visitNotation(self, node, start):
        if start:
            st = "<!NOTATION %s" % node.nodeName
            if node.publicId:
                st = st + ' PUBLIC "%s"' % node.publicId
                if node.systemId:
                    st = '%s "%s"' % (st, node.systemId)
            elif node.systemId:
                st = st + ' SYSTEM "%s"' % node.systemId
            self.stream.write(st + '>\n')

    def visitProcessingInstruction(self, node, start):
        if start:
            self.stream.write('<?')
            self.stream.write(node.target + ' ')
            self.stream.write(node.data)
            self.stream.write('?>')

    def visitComment(self, node, start):
        if start:
            self.stream.write('<!--')
            self.stream.write(node.data)
            self.stream.write('-->')

    def visitDocument(self, node, start):
        if start:
            if not self.html:
                self.stream.write('<?xml version="1.0"')
                if self.encoding:
                    self.stream.write(' encoding="%s"' % self.encoding)
                self.stream.write(' ?>\n')
        else:
            self.stream.write('\n') # Add a final newline

    def visitDocumentType(self, node, start):
        if start:
            if not node.entities.length and not node.notations.length and \
               not node.systemId:
                return

            self.stream.write("<!DOCTYPE " + node.name)
            if node.systemId:
                if node.publicId:
                    if '"' not in node.publicId:
                        self.stream.write(' PUBLIC "' + node.publicId + '" ')
                    else:
                        self.stream.write(" PUBLIC '" + node.publicId + "' ")
                else:
                    self.stream.write(' SYSTEM ')

                if '"' not in node.systemId:
                    self.stream.write('"' + node.systemId + '"')
                else:
                    self.stream.write("'" + node.systemId + "'")

            if node.internalSubset:
                self.stream.write(" [%s]" % node.internalSubset)
            elif node.entities.length or node.notations.length:
                self.stream.write(' [\n')
                for i in range(node.entities.length):
                    self.visitEntity(node.entities.item(i), start=1)
                for i in range(node.notations.length):
                    self.visitNotation(node.notations.item(i), start=1)
                self.stream.write(']')
            self.stream.write('>\n')

    def visitDocumentFragment(self, node, start):
        pass   # we're just here for the children

def _translateCdata(characters, allEntRefs = None, encoding='UTF-8'):
    """Translate characters into a legal format."""
    if not characters:
        return ''
    if allEntRefs: # translate all chars to entrefs; for attr value
        if g_cdataCharPattern.search(characters):
            new_string = g_cdataCharPattern.subn(
                lambda m, d=g_charToEntity: d[m.group()],
                characters)[0]
        else:
            new_string = characters
    else: # translate only required chars to entrefs
        if g_cdataCharPatternReq.search(characters):
            new_string = g_cdataCharPatternReq.subn(
                lambda m, d=g_charToEntityReq: d[m.group()],
                characters)[0]
        else:
            new_string = characters
    # This was never used, & I never got it anyway - prettyprinting?
    #if prev_chars[-2:] == ']]' and characters[0] == '>':
    #    new_string = '&gt;' + new_string[1:]
    # Note: use decimal char entity rep because some browsers are broken
    # FIXME: This will bomb for high characters.
    # Should, for instance, detect the UTF-8 for 0xFFFE
    # and put out &#xFFFE;
    if XML_ILLEGAL_CHAR_PATTERN.search(new_string):
        new_string = XML_ILLEGAL_CHAR_PATTERN.subn(
            lambda m: '&#%i;' % ord(m.group()),
            new_string)[0]
    #new_string = utf8_to_code(new_string, encoding) # XXX ugh
    return new_string

def _translateCdataAttr(characters):
    """
    Translate attribute value characters into a legal format;
    return the value and the delimiter used.
    """
    if not characters:
        return '', '"'
    if '"' not in characters or "'" in characters:
        delimiter = '"'
        new_chars = _translateCdata(characters, allEntRefs = 1)
        new_chars = re.sub("&apos;", "'", new_chars)
    else:
        delimiter = "'"
        new_chars = _translateCdata(characters, allEntRefs = 1)            
        new_chars = re.sub("&quot;", '"', new_chars)
    #FIXME: There's more to normalization
    #Convert attribute new-lines to character entity
    # characters is possibly shorter than new_chars (no entities)
    # I think this was a prettyprinting issue, newlines aren't illegal
    # http://www.xml.com/axml/target.html#NT-AttValue
    #if "\n" in characters:
    #    new_chars = re.sub('\n', '&#10;', new_chars)
    return new_chars, delimiter


=== Added File Products/ParsedXML/README.DOMProxy ===
How and why we are proxying DOM nodes.

 Parsed XML consists of two DOM interfaces.  Our DOM is a tight and fast
 implementation.  Our ManageableDOM (of which the ParsedXML object that
 is instantiated acts as the top object) contains an instance of a DOM
 tree, proxies its DOM interface, and also provides Zope support such
 as management interfaces.

 A Parsed XML object can be created from scratch, in which case its DOM
 document will be created with it, or it can be wrapped around an
 existing DOM document.
 
 Parsed XML objects should be able to provide some management support
 for any compliant DOM document, since it proxies DOM calls.  However,
 since it uses our builder, which is optimized for our DOM storage,
 parsing will not work on storages other than our DOM.

Why are we proxying?

 Our DOM implementation is fast and scalable, and we didn't want to
 compromise this with our extras.  Some users won't want or need the
 Zopish features to be married to the DOM implementation.

When should the proxy be used, and when should the simple DOM be used?

 There's no reason to use the proxies when you don't need their
 features.  If all that you need is a DOM storage, then the proxies
 aren't necessary, and you can create and use a DOM document without
 the proxy wrappers.  However, you will have to know what you are
 doing; some Zope machinery won't be taken care of for you:

  - The DOM storage doesn't keep track of any non-DOM attributes.
    For example, namespace usage and content type are stored by the
    proxy Document, and if you're not using this, you'll have
    to keep track of these attributes yourself, since the DOM doesn't
    keep track of them.
 
  - The DOM storage doesn't know about Zope permissions, so your
    containing object must handle this.

  - The DOM storage doesn't provide any persistence machinery,
    although it will acquire and call the persistence triggering
    methods when available, so storing it in a persistent container
    will suffice to persist the DOM.

 To create a DOM Document without any proxy wrappers, see
 createDOMDocument() in ParsedXML.py.

When should the proxy not be used?

 When you reference the proxied DOM object through a different
 persistent object, *and* change the DOM through that reference, *and*
 rely on get_size() or use a ZCache, *and* the ParsedXML Document
 isn't notified when the change occurs.

 The DOM objects persist by acquiring persistence methods from their
 containers.  The proxy objects update certain cached values when
 these methods are called.  That means that if a DOM Document is
 referenced by a different persistent object, and changes are made
 through that reference, the ParsedXML proxy won't know to update its
 cached values.

 ParsedXML caches the result of get_size(), and provides support for a
 ZCache to cache index_html.  If you use a ZCache with a ParsedXML
 instance, or rely on the result of get_size(), you will need to make
 sure that these values are updated if the DOM is modified through a
 reference other than the ParsedXML Document.  This can be done by
 calling __changed__() on the ParsedXML Document.

How are we proxying?

 Our DOM implementation is in the DOM subdirectory.

 The baseclasses for the DOMImplementation is in DOMProxy.py.  These
 define the machinery for proxying our DOM tree.  The basic proxying is
 defined here, except for methods to create the proxy nodes, which
 we'll describe soon.

 The base proxy class is DOMProxy.  It contains a reference to the
 actual DOM node it is proxying for.

 NodeProxy, ElementProxy, etc. all specialize DOMProxy for the
 appropriate DOM classes.

 These proxy classes all lack the ability to actually create instances
 of the proxy nodes.  This is because they are designed to be
 subclassed, and they don't yet know what class to wrap a DOM node into
 when they want a proxy object.  Subclasses should define the methods
 wrapDOMObj(), wrapNodeList() and wrapNamedNodeMap(). wrapDOMObj()
 and it should take a DOM Node and return the appropriate
 proxy node; wrapNodeList() and wrapNamedNodeMap() should take a 
 NodeList and NamedNodeMap object respectively and returned proxied
 versions.

 Because these methods are undefined, these baseclasses cannot be
 instantiated, they must be subclassed.  A simple example of a working
 implementation is in TransPubDOMProxy.py.

 The actual proxy classes that Parsed XML uses are in ManageableDOM.py,
 and the basic DOM baseclass is ManageableNode, which corresponds to a
 DOM node.  It mixes DOMProxy.NodeProxy with ManageableWrapper, which
 provides the needed methods that return ManageableNode, ManageableNodeList
 and ManageableNamedNodeMap subclasses. ManageableNode also mixes in
 DOMManageable, which provides our management and publishing support,
 and an Acquisition class.

 When a Parsed XML product is added to a Zope installation, a ParsedXML
 object is instantiated, which is a subclass of ManageableDocument.
 It is important to note that none of the other proxy nodes are
 persistent!  wrapDOMObj() wraps a new proxy node around an existing
 DOM node whenever it is called.  It never reuses existing proxy nodes,
 or even knows of their existence.  So although you can do things like
 assign non-DOM attributes to a ManageableNode, re-navigating to the
 ManageableNode corresponding to the same place in the DOM tree won't
 get you a node with those attributes, since it's a whole new instance.
 This also means that navigating with DOM calls is slower, because
 of all that instantiating and wrapping.  It's more efficient to work
 through the proxied DOM objects when you can and wrap the result when
 you must.

 There are ways to make persistent proxy objects if you're developing
 your own proxy classes based on ours, by inheriting a wrapDOMObj()
 method that makes persistent proxy objects and returns existing ones
 when appropriate.


=== Added File Products/ParsedXML/README.parseprint ===
DOM objects, XML, printing, and parsing

 ParsedXML doesn't store any XML.  It stores a DOM tree, which is an
 object representation of the data in an XML document; or perhaps it is
 more accurate to say that an XML document is a serial representation
 of some data, and the corresponding DOM tree is a hierarchical
 representation of the same data.

 The primary way of accessing and manipulating that data is with DOM
 API calls.  When a ParsedXML object is viewed as XML, the DOM tree is
 serialized into the XML which is viewed.  This is what is seen in the
 Edit management view.  When XML is inputted into a ParsedXML object,
 it is parsed to create DOM objects which are inserted into the DOM
 tree.  This is what happens when XML is edited or uploaded in the
 Edit management view.

 It is important to note that the DOM is not the XML because the
 information that each stores is not the same.  The XML specification
 states what information can be expressed by a well-formed XML
 document, and some of this information is not preserved by the
 parser, printer, and DOM storage.  For example, whitespace in
 attribute strings isn't significant.  The Infoset specification at
 "http://www.w3.org/TR/xml-infoset/" states what can be lost; parsers
 are also allowed certain liberties with their input.  Our parser,
 printer, and DOM keep more information than the Infoset requires,
 such as attribute order.

 Entities and entity references are an example of how the parser and
 printer manipulate XML.  Currently, entity references are expanded to
 their entities by the parser; it never adds entity reference nodes to
 the document.  This is legal, if annoying, behavior.  Because of
 this, when an XML file containing "&amp;" in a text node is parsed,
 the node will contain a literal "&" where the "&amp;" was in the XML.
 It is legal for a DOM text node to contain a literal "&" character.
 However, it is not legal for an XML text node to contain a literal
 "&", so when that node is printed, the "&" will be converted back
 into a "&amp;" entity reference.

=== Added File Products/ParsedXML/README.txt ===
README for Parsed XML.

What is it?

  Parsed XML allows you to use XML objects in the Zope environment.
  You can create XML documents in Zope and leverage Zope to format,
  query, and manipulate XML.

  Parsed XML consists of a DOM storage, a builder that uses PyExpat to
  parse XML into the DOM, and a management proxy product that provides
  Zope management features for a DOM tree. It also includes a system
  to create paths to nodes in Zope URLs (NodePath).
  
Requirements, Installation

  See INSTALL.txt.

Feedback, discussion, more information

  The latest released version can be found at the
  "product":http://www.zope.org/Members/faassen/ParsedXML
  site.

  For more information, see the Parsed XML
  "wiki":http://www.zope.org/Wikis/DevSite/Projects/ParsedXML.

  Bug reports and status is kept by the the Parsed XML
  "tracker":http://www.zope.org/Members/karl/ParsedXML/ParsedXMLTracker.

  There is a
  "mailing list":http://mail.zope.org/mailman/listinfo/parsed-xml-dev
  with archives.

  The latest version is available through
  "CVS":http://www.zope.org/Wikis/DevSite/Projects/ParsedXML/Releases.

Features

  The Parsed XML product parses XML into a Zopish DOM tree.  The
  elements of this tree support persistence, acquisition, etc..  The
  document and subnodes are editable and manageable through
  management proxy objects, and the underlying DOM tree can be directly
  manipulated via DTML, Python, etc..

  DOM and ManageableDOM

    We're implementing a lean, mean DOM tree for pure DOM access, and
    a tree of proxy shells to handle management and take care of the
    conveniences like publishing and security.  The ManageableNodes
    are the proxy objects.  These are what you see in the management
    interface, and the top object that gets put in the ZODB.  Note
    that only the top proxy object is persistent, the others are
    transient.  The Nodes are pure DOM objects.  From a
    ManageableNode, the DOM Node is retrieved with the getDOMObj()
    call.

    See README.DOMProxy for information about the proxy objects.

  DOM API support

    The DOM tree created by Zope aims to comply with the DOM level 2
    standard. This allows you to access your XML in DTML or External
    Methods using a standard and powerful API.

    We are currently supporting the DOM level 2 Core and Traversal
    specifications.
   
    The DOM tree is not built with the XML-SIG's DOM package, because
    it requires significantly different node classes.

    DOM attributes are made available according to the Python language
    mapping for the IDL interfaces described by the DOM
    recommendation; see the
    "mapping":http://cgi.omg.org/cgi-bin/doc?ptc/00-04-08.

  URL traversal


    Parsed XML implements a 'NodePath' system to create
    references to XML nodes (most commonly elements).

    FIXME include examples here
  
    Currently, traversal uses an element's index within its
    parent as an URL key. For example,
      
          'http://server/myDoc/0/2/mymethod'
        
    This URL traverses from an XML Document object with id 'myDoc' to
    it's first sub-element, to that element's second 
    sub-element to an acquired method with id 'myMethod'

    DOM methods can also be used in URLs, for example, 

          'http://server/myDoc/firstChild/nextSibling/mymethod' 
  
  Editing XML with the management interface

    XML Documents and subnodes are editable via the management
    interface. Documents and subtrees can be replaced by uploading XML
    files.

  Security

    Security is handled at the document level.  DOM attributes and
    methods are protected by the "Access contents information"
    permission.  Subnodes will acquire security settings from the
    document.

Developing with Parsed XML

  We like to think that Parsed XML provides a flexible platform for
  using a DOM storage and extending that storage to do interesting
  things.  See README.DOMProxy for an explanation of how we're using
  this for Parsed XML.

  We've included a comprehensive unit test suite to make testing for
  DOM compliance easier.  See tests/README for details.

  If you want to submit changes to Parsed XML, please use the test
  suite to make sure that your changes don't break anything.

Bugs

  There are bugs in how multiple node references reflect the hierarchy
  above the node:

    - A reference to a subnode of a DOM document won't reflect some
      hierarchy changes made on other references to the same node.
 
      If two references to a node are created, and one is then
      reparented, the other reference won't reflect the new parent.
      The parentNode attribute will be incorrect, for example, as well
      as the ownerDocument and ownerElement attributes.

    - A reference to a subnode of a DOM document can't be properly stored
      as a persistent attribute of a ZODB object; it will lose hierarchy
      information about its parent as well.

   Entity reference handling is not complete:

     - Entity references do not have child nodes that mirror the child
       nodes of the referenced entity; they do not have child nodes at all.

     - TreeWalker.expandEntityReferences has no effect, because of the
       above bug.

  Unicode support is still incomplete. It appears to work with
  Python 2.1 and Zope 2.4, but there are still some issues with the parser.

  Traversal support for visibility and roots is not complete.

Credits

  see CREDITS.txt and LICENSE.Fourthought.


=== Added File Products/ParsedXML/StrIO.py ===
"""Module which selects the right version of StringIO."""

# Python 2.1 and up is now a requirement, so we don't need to
# do anything special here
from StringIO import StringIO


=== Added File Products/ParsedXML/TransPubDOMProxy.py ===
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################
"""
A simple example implementation of DOMProxy.

Provide a class to implement wrapDOMObj(), mix that and the DOMProxy proxy
classes, and add whatever you want to make it interesting.
"""

import DOMProxy
import Acquisition

class TransPubWrapper:
    """
    Mixin class to go alongside DOMProxy classes.  Provides the wrapDOMObj
    function to create TransPubNode classes.  This is what makes TransPubNodes
    transient - we never re-use proxies, but create new ones when we need them.
    """
    
    # In the future we may want to return different proxy types based
    # on non-DOM node types, such as DB/nonDB.  Probably map
    # the same way that the DOM classes will map.
    def wrapDOMObj(self, node):
        """
        Return the appropriate manageable class wrapped around the Node.
        We never create Nodes ourselves, only wrap existing ones.
        Wrapped node can be single DOM object, a non-DOM object, or a
        container that contains only non-DOM objects - DOM objects in
        containters aren't wrapped.
        """
        from xml.dom import Node
        import types
        if node == None:
            return None
        elif isinstance(node, types.InstanceType) \
             and node.__class__.__name__ == "ChildNodeList": # XXX impl detail
            return TransPubNodeList(node)
        elif isinstance(node, types.InstanceType) \
             and node.__class__.__name__ == "AttributeMap": # XXX impl detail
            return TransPubNamedNodeMap(node)
        elif not hasattr(node, "nodeType"):
            return node                     # not DOM, don't wrap.
        elif node.nodeType == Node.ELEMENT_NODE:
            return TransPubElement(node)
        elif node.nodeType == Node.ATTRIBUTE_NODE:
            return TransPubAttr(node)
        elif node.nodeType == Node.TEXT_NODE:
            return TransPubText(node)
        elif node.nodeType == Node.CDATA_SECTION_NODE:
            return TransPubCDATASection(node)
        elif node.nodeType == Node.ENTITY_REFERENCE_NODE:
            return TransPubEntityReference(node)
        elif node.nodeType == Node.ENTITY_NODE:
            return TransPubEntity(node)
        elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
            return TransPubProcessingInstruction(node)
        elif node.nodeType == Node.COMMENT_NODE:
            return TransPubComment(node)
        elif node.nodeType == Node.DOCUMENT_NODE:
            return TransPubDocument(node)
        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
            return TransPubDocumentType(node)
        elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
            return TransPubDocumentFragment(node)
        elif node.nodeType == Node.NOTATION_NODE:
            return TransPubNotation(node)
        else:
            raise TypeError


_TRANS_PUB_DOM_PROXY_FEATURES = (
    ("org.zope.dom.acquisition", None),
    ("org.zope.dom.acquisition", "1.0"),
    )

class TransPubDOMImplementation(DOMProxy.DOMImplementationProxy):
    """
    A DOMImplementation proxy that implements createDocument to produce
    TransPubDocument instances.
    """

    def hasFeature(self, feature, version):
        feature = string.lower(feature)
        if (feature, version) in _TRANS_PUB_DOM_PROXY_FEATURES:
            return 1
        return self._domimplementation.hasFeature(feature, version)
    
    def createDocument(self, namespaceURI, qualifiedName, docType=None):
        DOMDocument = self._createDOMDocument(namespaceURI,
                                              qualifiedName, docType)
        return TransPubDocument(DOMDocument.aq_base) # XXX check aq

theDOMImplementation = TransPubDOMImplementation()

#DOMIO, DOMManageable, DOMPublishable,
class TransPubNode(TransPubWrapper, DOMProxy.NodeProxy, Acquisition.Implicit):
    "The core of the TransPub DOM proxies."
    pass

class TransPubNodeList(TransPubWrapper, DOMProxy.NodeListProxy):    
    "A TransPubWrapper mixer with NodeListProxy."
    pass

class TransPubNamedNodeMap(TransPubWrapper, DOMProxy.NamedNodeMapProxy):
    "A TransPubWrapper mixer with NamedNodeMapProxy."
    pass
    
class TransPubDocumentFragment(DOMProxy.DocumentFragmentProxy, TransPubNode):
    "A TransPubWrapper mixer with DocumentFragmentProxy."
    pass
    
class TransPubElement(DOMProxy.ElementProxy, TransPubNode):
    "A TransPubWrapper mixer with ElementProxy."
    pass

class TransPubCharacterData(DOMProxy.CharacterDataProxy, TransPubNode):
    "A TransPubWrapper mixer with CharacterDataProxy."
    pass

class TransPubCDATASection(DOMProxy.CDATASectionProxy, TransPubNode):
    "A TransPubWrapper mixer with CDATASectionProxy."
    pass

class TransPubText(TextProxy, DOMProxy.TransPubCharacterData):
    "A TransPubWrapper mixer with TextProxy."
    pass

class TransPubComment(CommentProxy, DOMProxy.TransPubCharacterData):
    "A TransPubWrapper mixer with CommentProxy."
    pass

class TransPubProcessingInstruction(DOMProxy.ProcessingInstructionProxy,
                                    TransPubNode):
    "A TransPubWrapper mixer with ProcessingInstructionProxy."
    pass

class TransPubAttr(DOMProxy.AttrProxy, TransPubNode):
    "A TransPubWrapper mixer with AttrProxy."
    pass

class TransPubDocument(DOMProxy.DocumentProxy, TransPubNode):
    """
    A TransPubWrapper mixer with DocumentProxy.
    Provides and protects the implementation attribute.
    """
    
    implementation = theDOMImplementation

    #block set of implementation, since we don't proxy it the same
    def __setattr__(self, name, value):
        if name == "implementation":
            raise xml.dom.NoModificationAllowedErr()
        # wacky ExtensionClass inheritance
        TransPubDocument.inheritedAttribute('__setattr__')(self, name, value)

# DOM extended interfaces

class TransPubEntityReference(DOMProxy.EntityReferenceProxy, TransPubNode):
    "A TransPubWrapper mixer with EntityReferenceProxy."
    pass

class TransPubEntity(DOMProxy.EntityProxy, TransPubNode):
    "A TransPubWrapper mixer with EntityProxy."
    pass

class TransPubNotation(DOMProxy.NotationProxy, TransPubNode):
    "A TransPubWrapper mixer with NotationProxy."
    pass

class TransPubDocumentType(DOMProxy.DocumentTypeProxy, TransPubNode):
    "A TransPubWrapper mixer with DocumentTypeProxy."
    pass



=== Added File Products/ParsedXML/__init__.py ===
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################

"""
Parsed XML product
"""

def initialize(context):
    import ParsedXML
    context.registerClass(
        ParsedXML.ParsedXML,
        permission = 'Add Documents, Images, and Files',
        icon='www/pxml.gif',
        constructors = (ParsedXML.manage_addParsedXMLForm,
                        ParsedXML.manage_addParsedXML)
        )
    context.registerHelp()
    context.registerHelpTitle('Parsed XML Help')
    #context.registerHelpTopic('ParsedXML_Edit', ParsedXML_Edit())


=== Added File Products/ParsedXML/main.dtml ===
<html><head></head><body>hello world</body></html>

=== Added File Products/ParsedXML/version.txt ===
ParsedXML 1.3.1





More information about the zopeorg-checkins mailing list