# HG changeset patch # User cmlenz # Date 1149318961 0 # Node ID 5479aae32f5a056df9f9e63a7e968d584222dfec # Parent 5f9862282a9d6fac3f4122ce092a9d5c6cfec974 Initial import. diff --git a/doc/2000ft.graffle b/doc/2000ft.graffle new file mode 100755 --- /dev/null +++ b/doc/2000ft.graffle @@ -0,0 +1,1094 @@ + + + + + ActiveLayerIndex + 0 + AutoAdjust + + CanvasColor + + w + 1 + + CanvasOrigin + {0, 0} + CanvasScale + 1 + ColumnAlign + 1 + ColumnSpacing + 36 + CreationDate + 2006-05-08 14:33:49 +0200 + Creator + chris + DisplayScale + 1 cm = 1 cm + GraphDocumentVersion + 5 + GraphicsList + + + Bounds + {{241.464, 258}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 50 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 ...} + + + + Class + LineGraphic + Head + + ID + 29 + + ID + 48 + OrthogonalBarAutomatic + + OrthogonalBarPosition + -1 + Points + + {372, 149.5} + {317.768, 149.5} + + Style + + stroke + + HeadArrow + FilledArrow + LineType + 2 + TailArrow + 0 + + + Tail + + ID + 46 + + + + Bounds + {{387.348, 138}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 47 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 Template} + + + + Bounds + {{372, 119}, {125.232, 61}} + Class + ShapedGraphic + FontInfo + + Color + + b + 1 + g + 1 + r + 1 + + Font + Helvetica-Bold + Size + 12 + + ID + 46 + Shape + Rectangle + Style + + fill + + Color + + b + 0.835052 + g + 0.669573 + r + 0.544872 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\i\b\fs24 \cf1 templating} + VerticalPad + 2 + + TextPlacement + 0 + + + Class + LineGraphic + Head + + ID + 29 + + ID + 45 + OrthogonalBarAutomatic + + OrthogonalBarPosition + -1 + Points + + {168, 149.5} + {222.232, 149.5} + + Style + + stroke + + HeadArrow + FilledArrow + LineType + 2 + TailArrow + 0 + + + Tail + + ID + 44 + + + + Bounds + {{58.1159, 138}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 43 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 Fragment} + + + + Class + LineGraphic + Head + + ID + 23 + + ID + 41 + OrthogonalBarAutomatic + + OrthogonalBarPosition + -1 + Points + + {270, 299} + {270, 328} + + Style + + stroke + + HeadArrow + FilledArrow + LineType + 2 + TailArrow + 0 + + + Tail + + ID + 34 + + + + Class + LineGraphic + Head + + ID + 29 + + ID + 40 + OrthogonalBarAutomatic + + OrthogonalBarPosition + -1 + Points + + {270, 83} + {270, 133.5} + + Style + + stroke + + HeadArrow + FilledArrow + LineType + 2 + TailArrow + 0 + + + Tail + + ID + 26 + + + + Class + LineGraphic + Head + + ID + 34 + + ID + 39 + OrthogonalBarAutomatic + + OrthogonalBarPosition + -1 + Points + + {270, 165.5} + {270, 210} + + Style + + stroke + + HeadArrow + FilledArrow + LineType + 2 + TailArrow + 0 + + + Tail + + ID + 29 + + + + Bounds + {{241.464, 220}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 37 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 Whitespace Filter} + + + + Bounds + {{126, 220}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 36 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 XInclude Filter} + + + + Bounds + {{126, 258}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 35 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 HTML Sanitizer} + + + + Bounds + {{116, 210}, {308, 89}} + Class + ShapedGraphic + FontInfo + + Color + + b + 1 + g + 1 + r + 1 + + Font + Helvetica-Bold + Size + 12 + + ID + 34 + Shape + Rectangle + Style + + fill + + Color + + b + 0.835052 + g + 0.669573 + r + 0.544872 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + Draws + NO + + + Text + + Align + 2 + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qr\pardirnatural + +\f0\i\b\fs24 \cf1 filtering} + + + + Bounds + {{222.732, 134}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 11 + + ID + 29 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 Stream} + + + + Bounds + {{241.464, 42}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 28 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 XML Parser} + + + + Bounds + {{126, 42}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 27 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 HTML Parser} + + + + Bounds + {{116, 32}, {308, 51}} + Class + ShapedGraphic + FontInfo + + Color + + b + 1 + g + 1 + r + 1 + + Font + Helvetica-Bold + Size + 12 + + ID + 26 + Shape + Rectangle + Style + + fill + + Color + + b + 0.835052 + g + 0.669573 + r + 0.544872 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + Draws + NO + + + Text + + Align + 2 + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qr\pardirnatural + +\f0\i\b\fs24 \cf1 parsing} + + + + Bounds + {{241.464, 338}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 25 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 XML Serializer} + + + + Bounds + {{126, 338}, {94.5364, 31}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 24 + Shape + Rectangle + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs22 \cf0 HTML Serializer} + + + + Bounds + {{116, 328}, {308, 51}} + Class + ShapedGraphic + FontInfo + + Color + + b + 1 + g + 1 + r + 1 + + Font + Helvetica-Bold + Size + 12 + + ID + 23 + Shape + Rectangle + Style + + fill + + Color + + b + 0.835052 + g + 0.669573 + r + 0.544872 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + Draws + NO + + + Text + + Align + 2 + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qr\pardirnatural + +\f0\i\b\fs24 \cf1 serialization} + + + + Bounds + {{42.7682, 119}, {125.232, 61}} + Class + ShapedGraphic + FontInfo + + Color + + b + 1 + g + 1 + r + 1 + + Font + Helvetica-Bold + Size + 12 + + ID + 44 + Shape + Rectangle + Style + + fill + + Color + + b + 0.835052 + g + 0.669573 + r + 0.544872 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-BoldOblique;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\i\b\fs24 \cf1 building} + VerticalPad + 2 + + TextPlacement + 0 + + + GridInfo + + GuidesLocked + NO + GuidesVisible + YES + HPages + 1 + ImageCounter + 1 + IsPalette + NO + KeepToScale + + Layers + + + Lock + NO + Name + Ebene 1 + Print + YES + View + YES + + + LayoutInfo + + LayoutTarget + 3 + + LinksVisible + NO + MagnetsVisible + NO + MasterSheets + + + ActiveLayerIndex + 0 + AutoAdjust + + CanvasColor + + w + 1 + + CanvasOrigin + {0, 0} + CanvasScale + 1 + ColumnAlign + 1 + ColumnSpacing + 36 + DisplayScale + 1 cm = 1 cm + GraphicsList + + GridInfo + + HPages + 1 + IsPalette + NO + KeepToScale + + Layers + + + Lock + NO + Name + Ebene 1 + Print + YES + View + YES + + + LayoutInfo + + LayoutTarget + 3 + + Orientation + 2 + RowAlign + 1 + RowSpacing + 36 + SheetTitle + Master 1 + UniqueID + 1 + VPages + 1 + + + ModificationDate + 2006-05-09 01:09:46 +0200 + Modifier + chris + NotesVisible + NO + Orientation + 2 + OriginVisible + NO + PageBreaks + YES + PrintInfo + + NSPaperSize + + size + {595.276, 841.89} + + + ReadOnly + NO + RowAlign + 1 + RowSpacing + 36 + SheetTitle + Arbeitsfläche 1 + SmartAlignmentGuidesActive + YES + SmartDistanceGuidesActive + NO + UniqueID + 1 + UseEntirePage + + VPages + 1 + WindowInfo + + CurrentSheet + 0 + DrawerOpen + + DrawerTab + Outline + DrawerWidth + 209 + FitInWindow + + Frame + {{28, 214}, {757, 512}} + ShowRuler + + ShowStatusBar + + VisibleRegion + {{-109, 0}, {742, 422}} + Zoom + 1 + + + diff --git a/doc/2000ft.png b/doc/2000ft.png new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..11d29cedacb43203e5ea6f8dfe1278c7ac208a72 GIT binary patch literal 22649 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 from markup.input import XML +>>> doc = XML('My document') + +This results in a `Stream` object that can be used in a number of way. + +>>> doc.render(method='html', encoding='utf-8') +'My document' + +>>> from markup.input import HTML +>>> doc = HTML('My document</HTML>') +>>> doc.render(method='html', encoding='utf-8') +'<html lang="en"><head><title>My document' + +>>> title = doc.select('head/title') +>>> title.render(method='html', encoding='utf-8') +'My document' + + +Markup streams can also be generated programmatically using the +`markup.builder` module: + +>>> from markup.builder import tag +>>> doc = tag.DOC(tag.TITLE('My document'), lang='en') +>>> doc.generate().render(method='html') +'My document' + +""" + +from markup.core import * +from markup.input import XML, HTML diff --git a/markup/builder.py b/markup/builder.py new file mode 100644 --- /dev/null +++ b/markup/builder.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2006 Christopher Lenz +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.com/license.html. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://projects.edgewall.com/trac/. + +from markup.core import Attributes, QName, Stream + +__all__ = ['Fragment', 'Element', 'tag'] + + +class Fragment(object): + __slots__ = ['children'] + + def __init__(self): + self.children = [] + + def append(self, node): + """Append an element or string as child node.""" + if isinstance(node, (Element, basestring, int, float, long)): + # For objects of a known/primitive type, we avoid the check for + # whether it is iterable for better performance + self.children.append(node) + elif isinstance(node, Fragment): + self.children += node.children + elif node is not None: + try: + children = iter(node) + except TypeError: + self.children.append(node) + else: + for child in node: + self.append(children) + + def __add__(self, other): + return Fragment()(self, other) + + def __call__(self, *args): + for arg in args: + self.append(arg) + return self + + def generate(self): + """Generator that yield tags and text nodes as strings.""" + def _generate(): + for child in self.children: + if isinstance(child, Fragment): + for event in child.generate(): + yield event + else: + yield Stream.TEXT, child, (-1, -1) + return Stream(_generate()) + + def __iter__(self): + return iter(self.generate()) + + def __str__(self): + return str(self.generate()) + + def __unicode__(self): + return unicode(self.generate()) + + +class Element(Fragment): + """Simple XML output generator based on the builder pattern. + + Construct XML elements by passing the tag name to the constructor: + + >>> print Element('strong') + + + Attributes can be specified using keyword arguments. The values of the + arguments will be converted to strings and any special XML characters + escaped: + + >>> print Element('textarea', rows=10, cols=60) +