from Products.Silva.silvaxml.xmlexport import theXMLExporter, VersionedContentProducer, SilvaBaseProducer from sprout.saxext.html2sax import saxify from Products.ParsedXML.DOM.Core import Node SilvaDocumentNS = 'http://infrae.com/ns/silva_document' def initializeXMLExportRegistry(): """Here the actual content types are registered. Non-Silva-Core content types probably need to register themselves in in their product __init__.pies """ from Products.SilvaDocument.Document import Document, DocumentVersion exporter = theXMLExporter exporter.registerNamespace('doc', SilvaDocumentNS) exporter.registerProducer(Document, DocumentProducer) exporter.registerProducer(DocumentVersion, DocumentVersionProducer) class DocumentProducer(VersionedContentProducer): """Export a Silva Document object to XML. """ def sax(self): self.startElement('document', {'id': self.context.id}) self.workflow() self.versions() self.endElement('document') class DocumentVersionProducer(SilvaBaseProducer): """Export a version of a Silva Document object to XML. """ def sax(self): self.startElement('content', {'version_id': self.context.id}) self.metadata() node = self.context.content.documentElement.getDOMObj() self.sax_node(node) self.endElement('content') def sax_node(self, node): """Export child nodes of a (version of a) Silva Document to XML """ attributes = {} if node.attributes: for key in node.attributes.keys(): attributes[key] = node.attributes[key].value self.startElementNS(SilvaDocumentNS, node.nodeName, attributes) if node.nodeName == 'source' and node.parentNode.nodeName != 'cite': self.sax_source(node, attributes['id']) elif node.nodeName == 'toc' and self.getSettings().externalRendering(): self.sax_toc(node, attributes['toc_depth']) elif node.hasChildNodes(): for child in node.childNodes: if child.nodeType == Node.TEXT_NODE: if child.nodeValue: self.handler.characters(child.nodeValue) elif child.nodeType == Node.ELEMENT_NODE: if child.nodeName == 'table': self.sax_table(child) elif child.nodeName == 'image': self.sax_img(child) else: self.sax_node(child) else: if node.nodeValue: self.handler.characters(node.nodeValue) self.endElementNS(SilvaDocumentNS, node.nodeName) def sax_source(self, node, id): try: from Products.SilvaExternalSources.ExternalSource import getSourceForId except ImportError: return source = getSourceForId(self.context, id) parameters = {} for child in node.childNodes: if child.nodeName == 'parameter': self.startElementNS(SilvaDocumentNS, 'parameter', {'key': child.attributes['key'].value}) for grandChild in child.childNodes: text = '' if grandChild.nodeType == Node.TEXT_NODE: if grandChild.nodeValue: self.handler.characters(grandChild.nodeValue) text = text + grandChild.nodeValue parameters[str(child.attributes['key'].value)] = text self.endElementNS(SilvaDocumentNS, 'parameter') if self.getSettings().externalRendering(): html = source.to_html(self.context.REQUEST, **parameters) self.render_html(html) def sax_table(self, node): attributes = {} if node.attributes: for key in node.attributes.keys(): attributes[key] = node.attributes[key].value self.startElementNS(SilvaDocumentNS, 'table', attributes) columns_info = self.get_columns_info(node) nr_of_columns = len(columns_info) for column in columns_info: col_attributes = {'width': column['html_width'], 'class': 'align-' + column['align']} self.startElementNS(SilvaDocumentNS, 'col' , col_attributes) self.endElementNS(SilvaDocumentNS, 'col') if node.hasChildNodes(): row = 0 for child in node.childNodes: if child.nodeName == 'row_heading': self.sax_row_heading(child, nr_of_columns) elif child.nodeName == 'row': row += 1 self.sax_row(child, row, columns_info) self.endElementNS(SilvaDocumentNS, 'table') def sax_row_heading(self, node, nr_of_columns): child_attrs = {'colspan': str(nr_of_columns)} self.startElementNS(SilvaDocumentNS, 'row_heading', child_attrs) if node.hasChildNodes: for child in node.childNodes: if child.nodeType == Node.TEXT_NODE: if child.nodeValue: self.handler.characters(child.nodeValue) elif child.nodeType == Node.ELEMENT_NODE: self.sax_node(child) self.endElementNS(SilvaDocumentNS, 'row_heading') def sax_row(self, node, row, columns_info): child_attrs = {'class': row % 2 and "odd" or "even"} self.startElementNS(SilvaDocumentNS, 'row', child_attrs) if node.hasChildNodes: col = 0 for child in node.childNodes: if child.nodeType == Node.ELEMENT_NODE: self.sax_field(child, columns_info[col]) col += 1 self.endElementNS(SilvaDocumentNS, 'row') def sax_field(self, node, col_info): child_attrs = {'class': 'align-' + col_info['align']} self.startElementNS(SilvaDocumentNS, 'field', child_attrs) if node.hasChildNodes(): for child in node.childNodes: if child.nodeType == Node.TEXT_NODE: if child.nodeValue: self.handler.characters(child.nodeValue) else: # XXX UGLY EVIL HACK to make this behave the same as # the widget renderer, i.e. remove the tags of the # first child if it is a
if child is node.firstChild and child.nodeName == 'p':
for grandchild in child.childNodes:
if grandchild.nodeType == Node.TEXT_NODE:
self.handler.characters(grandchild.nodeValue)
else:
self.sax_node(grandchild)
else:
self.sax_node(child)
self.endElementNS(SilvaDocumentNS, 'field')
def get_columns_info(self, node):
columns = int(node.getAttribute('columns'))
if node.hasAttribute('column_info'):
column_info = node.getAttribute('column_info')
else:
result = []
for i in range(columns):
result.append({'align': 'left', 'width': 1, 'html_width':'%s%%' % (100/columns) })
node.REQUEST.set('columns_info', result)
return result
lookup = { 'L':'left', 'C':'center', 'R': 'right' }
result = []
for info in column_info.split():
info = info.split(':')
try:
align = info[0]
except IndexError:
align = 'L'
try:
width = int(info[1])
except IndexError:
width = 1
except ValueError:
width = 1
result.append({
'align': lookup.get(align, 'L'),
'width': width,
})
# too much info, ignore it
if len(result) > columns:
result = result[:columns]
# not enough info, take average and add to missing columns
elif len(result) < columns:
total = 0
for info in result:
total += info['width']
average = total / len(result)
for i in range(columns - len(result)):
result.append({'align': 'left', 'width': average })
# calculate percentages
total = 0
for info in result:
total += info['width']
for info in result:
percentage = int((float(info['width'])/total) * 100)
info['html_width'] = '%s%%' % percentage
return result
def sax_toc(self, node, depth):
# XXX hack to get the right context for the toc, in case we're
# actually rendering a ghost. This probably will change (for the
# better:) in Silva 1.2 or later.
toc_context = self.context
request = getattr(self.context, 'REQUEST', None)
if request is not None:
ghost_model = getattr(request, 'ghost_model', None)
if ghost_model is not None:
toc_context = ghost_model
public = self.context.version_status() == 'public'
if public:
tree = toc_context.get_public_tree(depth)
append_to_url = ''
else:
tree = toc_context.get_tree(depth)
append_to_url = 'edit/tab_preview'
text = ''
for obj in tree:
indent = obj[0]
item = obj[1]
if public:
title = item.get_title()
else:
title = item.get_title_editable()
url = item.absolute_url()
if indent > 0:
text = text + '
' % (
str(indent * 24),
self.context.REQUEST['BASE2']
)
text = text + '%s
' % (
url,
append_to_url,
title
)
html = '
%s
' % text self.render_html(html) def sax_img(self, node): """Unfortunately