[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_typeqUFolderq
UidqUslidequ}q(hh
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
UDTMLDocumentqttQU_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.PythonScriptqUPythonScriptqttQUidq Uslideq
U__ac_local_roles__q}qUkarlq
]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+UDTMLDocumentq,ttQU_ownerq-(]q.U acl_usersq/aUkarlq0tq1USlidesq2(U q3(UProducts.ParsedXML.ParsedXMLq4U ParsedXMLq5ttQU viewSlideq6(U ®q7(UOFS.DTMLMethodq8U
DTMLMethodq9ttQh((U µq:(hUPythonScriptq;ttQUtitleq<U h$(U ²q=(hUPythonScriptq>ttQUdomURLq?(U ´q@(hUPythonScriptqAttQu. à((UOFS.DTMLDocumentqUDTMLDocumentqtqNt.}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]qUOwnerq
asUglobalsq}qU__name__qUtreeqU_varsq}qu. » :((UProducts.ParsedXML.ParsedXMLqU ParsedXMLqtqNt.}q(UidqUTreeqU_persistentDocq(U »q(hU ParsedXMLq ttQU
_containerq
NU__ac_local_roles__q}qUkarlq
]qUOwnerqasUtitleqU UcontentTypeqUtext/xmlqUnoNamespacesqK 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&NUprefixq6NUnamespaceURIq7NubhNRq8}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.PythonScriptqUPythonScriptqtqNt.}q(U func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq (Unodeq
U
$loop_watcherqU$read_guardqU$write_guardq
U$guardqtUco_argcountqK ubUidqU nextSlideqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKUt } | 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 containerq3Uname_subpathq4Utraverse_subpathq5Uname_contextq6Ucontextq7Uname_m_selfq8Uscriptq9usbUPython_magicq:UN
q;U
func_defaultsq<Nu. "((UOFS.DTMLDocumentqUDTMLDocumentqtqNt.}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]qUOwnerq
asUglobalsq}qU__name__qUslideqU_varsq}qu. Ã((UProducts.ParsedXML.ParsedXMLqU ParsedXMLqtqNt.}q(UidqUSlidesqU_persistentDocq(U q(hU ParsedXMLq ttQU
_containerq
NU__ac_local_roles__q}qUkarlq
]qUOwnerqasUtitleqU UcontentTypeqUtext/xmlqUnoNamespacesqK 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>NUnamespaceURIq?Nubh&NRq@}qA(h)U
qBh+hBubeh"UslideqCh$hCh>Nh?Nubh&NRqD}qE(h)U
qFh+hFubhNRqG}qH(h]qI]qJ(Nh0NNUsecond 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
]qUOwnerqasUglobalsq
}qU__name__qU viewSlideqU_varsq}qu. µ {((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq (Unodeq
U
$loop_watcherqU$read_guardqU$write_guardq
U$guardqtUco_argcountqK ubUidqUgetColorqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKUt } | t } t } t } t } x[ | oP | | i d o | | i d Sn | | i } | q1 W t Sd Sq(NUcolorqtq(UcontextqUnodeqUhasAttributeqUgetAttributeqU
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 containerq4Uname_subpathq5Utraverse_subpathq6Uname_contextq7Ucontextq8Uname_m_selfq9Uscriptq:usbUPython_magicq;UN
q<U
func_defaultsq=Nu. ² Á((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq (Unodeq
U
$loop_watcherqU$read_guardqU$write_guardq
U$guardqtUco_argcountqK ubUidqU
previousSlideqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(K KKKUt } | 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 containerq3Uname_subpathq4Utraverse_subpathq5Uname_contextq6Ucontextq7Uname_m_selfq8Uscriptq9usbUPython_magicq:UN
q;U
func_defaultsq<Nu. ´ ¸((U#Products.PythonScripts.PythonScriptqUPythonScriptqtqNt.}q(U func_codeq(cShared.DC.Scripts.Signature
FuncCode
qoq}q(Uco_varnamesq (UURLstrq
UnodeqU
$loop_watcherqU$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
parentNodeqUtpURLqUabsolute_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 containerq4Uname_contextq5Ucontextq6Uname_subpathq7Utraverse_subpathq8Uname_nsq9U_Uname_m_selfq:Uscriptq;usbUPython_magicq<UN
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 = {
'&': '&',
'<': '<',
']]>': ']]>',
}
# characters that we must turn to entrefs in attr values:
g_cdataCharPattern = re.compile('[&<>"\']|]]>')
g_charToEntity = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
']]>': ']]>',
}
# 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("'", "'", new_chars)
else:
delimiter = "'"
new_chars = _translateCdata(characters, allEntRefs = 1,
encoding=encoding)
new_chars = re.sub(""", '"', 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 = {
'&': '&',
'<': '<',
']]>': ']]>',
}
# characters that we must turn to entrefs in attr values:
g_cdataCharPattern = re.compile('[&<>"\']|]]>')
g_charToEntity = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
']]>': ']]>',
}
# 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 < 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 = '>' + 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 
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("'", "'", new_chars)
else:
delimiter = "'"
new_chars = _translateCdata(characters, allEntRefs = 1)
new_chars = re.sub(""", '"', 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', ' ', 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 "&" in a text node is parsed,
the node will contain a literal "&" where the "&" 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 "&" 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