<?xml version='1.0' encoding='utf-8'?>
<spc:wrap xmlns="http://xmlns.livinglogic.de/xist/ns/doc" xmlns:spc="http://xmlns.livinglogic.de/xist/ns/specials">
<p>&xist; is an extensible &html;/&xml; generator written in Python.
It was developed as a replacement for an &html; preprocessor named
<app moreinfo="https://github.com/mbethke/hsc">HSC</app>
and borrows some features and ideas from it. It also borrows the basic ideas
(&xml;/&html; elements as Python objects) from
<app moreinfo="http://www.linuxjournal.com/article/2986">HTMLgen</app>
or <app moreinfo="http://dustman.net/andy/python/HyperText/">HyperText</app>.</p>

<p>(If you're impatient, there's also a
<a href="Examples.html">list of examples</a> that shows what can
be done with &xist;.)</p>

<section><h>Overview</h>
<p>&xist; can be used as a compiler that reads an input &xml; file and
generates a transformed output file, or it could be used for generating &xml;
dynamically inside a web server (but note that handling object trees <em>is</em>
slower than simply sending string fragments). In either case generating the
final &html; or &xml; output requires the following three steps:</p>
<ul>
<li>Generating a source &xml; tree: This can be done either by parsing an &xml;
file, or by directly constructing the tree &mdash; as <app>HTMLgen</app> and
<app>HyperText</app> do &mdash; as a tree of Python objects. &xist; provides a
very natural and pythonic &api; for that.</li>
<li>Converting the source tree into a target tree: This target tree can be a
&html; tree or a &svg; tree or XSL-FO tree or any other &xml; tree you like.
Every node class provides a <meth>convert</meth> method for performing this
conversion. For your own &xml; element types you have to define your own element
classes and implement an appropriate <meth>convert</meth> method. This is
possible for processing instructions and entity references too.</li>
<li>Publishing the target tree: For generating the final output a
<class>Publisher</class> object is used that generates the encoded byte string
fragments that can be written to an output stream (or yielded from a WSGI
application, etc.).</li></ul>
</section>


<section><h>Constructing &xml; trees</h>
<p>Like any other &xml; tree &api;, &xist; provides the usual classes:</p>
<ul>
<li><pyref module="ll.xist.xsc" class="Element"><class>Element</class></pyref> for &xml; elements;</li>
<li><pyref module="ll.xist.xsc" class="Attr"><class>Attr</class></pyref> for attributes;</li>
<li><pyref module="ll.xist.xsc" class="Attrs"><class>Attrs</class></pyref> for attribute mappings;</li>
<li><pyref module="ll.xist.xsc" class="Text"><class>Text</class></pyref> for text data;</li>
<li><pyref module="ll.xist.xsc" class="Frag"><class>Frag</class></pyref> for document fragments,
(a <class>Frag</class> object is simply a list of nodes);</li>
<li><pyref module="ll.xist.xsc" class="Comment"><class>Comment</class></pyref> for &xml; comments
(e.g. <markup>&lt;!-- the comment --&gt;</markup>);</li>
<li><pyref module="ll.xist.xsc" class="ProcInst"><class>ProcInst</class></pyref> for processing instructions
(e.g. <markup>&lt;?php echo $spam;?&gt;</markup>);</li>
<li><pyref module="ll.xist.xsc" class="Entity"><class>Entity</class></pyref> for entity references
(e.g. <markup>&amp;parrot;</markup>) and</li>
<li><pyref module="ll.xist.xsc" class="DocType"><class>DocType</class></pyref> for document type
declarations (e.g. <markup>&lt;!DOCTYPE html PUBLIC <rep>...</rep>&gt;</markup>).</li>
</ul>

<section><h>Creating plain elements, processing instructions and entities</h>

<section><h>Creating elements</h>

<p>Creating an element can be done with the function
<pyref module="ll.xist.xsc" function="element"><func>element</func></pyref>. Its signature looks
like this:</p>
<prog>
element(xmlns, xmlname, *content, **attrs)
</prog>

<p><obj>xmlns</obj> is the namespace name (e.g. <lit>"http://www.w3.org/1999/xhtml"</lit>
for HTML), and <obj>xmlname</obj> is the name of the element. Additional positional
arguments (i.e. items in <obj>content</obj>) will be the child nodes of the
element node. Keyword arguments will be attributes. You can pass most of Python's
builtin types to <func>element</func>. Strings and integers will be automatically
converted to <pyref module="ll.xist.xsc" class="Text"><class>Text</class></pyref>
objects. Constructing an &html; element works like this:</p>

<example><h>The first example</h>
<prog>
from ll.xist import xsc

html_xmlns = "http://www.w3.org/1999/xhtml"

node = xsc.element(
	html_xmlns,
	"div",
	"Hello ",
	xsc.element(
		html_xmlns,
		"a",
		"Python",
		href="http://www.python.org/"
	),
	" world!"
)
</prog>
</example>

<p>To output this element again, the method <pyref module="ll.xist.xsc" class="Node" method="bytes"><meth>bytes</meth></pyref> can be used:</p>

<example><h>Output of the first example</h>
<prog>
<prompt>&gt;&gt;&gt; </prompt><input>node.bytes()</input>
<![CDATA[b'<div>Hello <a href="http://www.python.org/">Python</a> world!</div>']]>
</prog>
</example>

<p>If you want a namespace declaration you can use the <obj>prefixdefault</obj>
argument:</p>

<example><h>The first example with an <lit>xmlns</lit> declaration</h>
<prog>
<prompt>&gt;&gt;&gt; </prompt><input>node.bytes(prefixdefault=None)</input>
<![CDATA[b'<div xmlns="http://www.w3.org/1999/xhtml">Hello <a href="http://www.python.org/">Python</a> world!</div>']]>
</prog>
</example>

<p>For attribute names that collide with Python keywords
or are not legal identifiers (most notably <lit>class</lit> in &html;)
you can pass the attributes as a dictionary to <func>xsc.element</func>:</p>
<example><h>Passing attributes as dictionaries</h>
<prog>
node = xsc.element(
	html_xmlns,
	"div",
	"Hello world!",
	{"class": "greeting", "id": 42, "title": "Greet the world"},
)
</prog>
</example>

</section>

<section><h>Creating processsing instructions</h>

<p>Processing instructions can be created with the function
<pyref module="ll.xist.xsc" function="procinst"><func>procinst</func></pyref>. Its signature looks
like this:</p>

<prog>
procinst(xmlname, *content)
</prog>

<p>So to create and print a processsing instruction named <lit>code</lit> with
the content <lit>x = 42</lit>, you can do the following (the method
<pyref module="ll.xist.xsc" class="Node" method="string"><meth>string</meth></pyref>
is simliar to <meth>bytes</meth>, but returns a <class>str</class> object
instead of a <class>bytes</class> object):</p>

<example><h>Creating and printing a processsing instruction</h>
<prog>
from ll.xist import xsc

node = xsc.procinst("code", "x = 42")
print(node.string())
</prog>
</example>

<p>This will output:</p>

<prog>
<![CDATA[<?code x = 42?>]]>
</prog>

</section>

<section><h>Creating entity references</h>

<p>Finally entity references can be created with the function
<pyref module="ll.xist.xsc" function="entity"><func>entity</func></pyref>:</p>

<example><h>Creating and printing an entity reference</h>
<prog>
from ll.xist import xsc

node = xsc.entity("html")
print(node.string())
</prog>
</example>

<p>This will output:</p>

<prog>
<![CDATA[&html;]]>
</prog>

</section>


<section><h>Creating &xml; trees with <lit>with</lit> blocks</h>

<p>Furthermore it's possible to use <lit>with</lit> blocks to construct
&xist; trees. Inside a <lit>with</lit> block the unary <lit>+</lit> operator
or the <func>add</func> function can be used to add nodes or attributes
to the current level of the tree:</p>
<example><h>Using <lit>with</lit> blocks</h>
<prog>
from ll.xist import xsc

html_xmlns = "http://www.w3.org/1999/xhtml"

with xsc.build():
	with xsc.element(html_xmlns, "div", {"class": "quote"}) as node:
		with xsc.element(html_xmlns, "h1", "Confucius (551-479 BC)"):
			xsc.add({"class": "author"})
		with xsc.element(html_xmlns, "ol"):
			+xsc.element(html_xmlns, "li", "I hear and I forget.")
			+xsc.element(html_xmlns, "li", "I see and I believe.")
			+xsc.element(html_xmlns, "li", "I do and I understand.")
</prog>
</example>

<p><class>xsc.build</class> must be used as the top level with block, so that
&xist; knows what to do with the nodes inside the block.</p>
</section>

<section><h>Creating &xml; trees from &xml; files</h>
<p>&xml; trees can also be generated by parsing &xml; files.
For this the module <pyref module="ll.xist.parse"><mod>ll.xist.parse</mod></pyref>
provides several tools.</p>

<p>For example, parsing a string can be done like this:</p>
<example><h>Parsing a string</h>
<prog><![CDATA[
from ll.xist import parse

node = parse.tree(
	b"<p xmlns='http://www.w3.org/1999/xhtml'>Hello <a href='http://www.python.org/'>Python</a> world!</p>",
	parse.Expat(ns=True),
	parse.Node()
)
]]></prog>
</example>

<p>For further info about the arguments to the parsing functions, see the
documentation for
<pyref module="ll.xist.parse"><mod>ll.xist.parse</mod></pyref>.</p>
</section>

</section>

<section><h>&xml; trees as Python objects</h>
<p>&xist; works somewhat different from a normal &dom; &api;.
Instead of only one element class, &xist; has one class for every element
type. All the elements from different &xml; vocabularies known to &xist; are
defined in modules in the <pyref module="ll.xist.ns"><mod>ll.xist.ns</mod></pyref>
subpackage. (Of course it's possible to define additional element classes for your
own &xml; vocabulary). The definition of &html; can be found in
<pyref module="ll.xist.ns.html"><mod>ll.xist.ns.html</mod></pyref>
for example.</p>

<p>Every element class has a constructor of the form:</p>
<prog>
__init__(self, *content, **attrs)
</prog>
<p>Positional arguments (i.e. items in <obj>content</obj>)
will be the child nodes of the element node. Keyword arguments will be attributes.
You can pass most of Python's builtin types to such a constructor.
Strings and integers will be automatically converted to
<pyref module="ll.xist.xsc" class="Text"><class>Text</class></pyref> objects.
Constructing an &html; element works like this:</p>
<example><h>The first example</h>
<prog>
from ll.xist.ns import html

node = html.div(
	"Hello ",
	html.a("Python", href="http://www.python.org/"),
	" world!"
)
</prog>
</example>

<p>For attribute names that collide with Python keywords
or are not legal identifiers (most notably <lit>class</lit> in &html;)
the attribute name must be slightly modified, so that it's a legal
Python identifier (for <lit>class</lit> an underscore is appended):</p>
<example><h>Illegal attribute names</h>
<prog>
node = html.div(
	"Hello world!",
	class_="greeting"
)
</prog>
</example>
<p>(Don't worry: This modified attribute name will be mapped to the real official attribute
name once the output is generated.)</p>

<p>You can pass attributes as a dictionary too:</p>
<example><h>Passing attributes as dictionaries</h>
<prog>
node = html.div(
	"Hello world!",
	dict(class_="greeting", id=42, title="Greet the world")
)
</prog>
</example>

<p>Furthermore it's possible to use <lit>with</lit> blocks to construct
&xist; trees. Inside a <lit>with</lit> block the unary <lit>+</lit> operator
or the <func>add</func> function can be used to add nodes or attributes
to the current level of the tree:</p>
<example><h>Using <lit>with</lit> blocks</h>
<prog>
with xsc.build():
	with html.div(class_="quote") as node:
		with html.h1("Confucius (551-479 BC)"):
			xsc.add(class_="author")
		with html.ol():
			+html.li("I hear and I forget.")
			+html.li("I see and I believe.")
			+html.li("I do and I understand.")
</prog>
</example>

<p><class>xsc.build</class> must be used as the top level with block, so that &xist;
knows what to do with the nodes inside the block.</p>
</section>

<section><h>Generating &xml; trees from &xml; files</h>
<p>&xml; trees can also be generated by parsing &xml; files.
For this the module <pyref module="ll.xist.parse"><mod>ll.xist.parse</mod></pyref>
provides several tools.</p>

<p>For example, parsing a string can be done like this:</p>
<example><h>Parsing a string</h>
<prog><![CDATA[
from ll.xist import parse
from ll.xist.ns import html

node = parse.tree(
	b"<p>Hello <a href='http://www.python.org/'>Python</a> world!</p>",
	parse.Expat(),
	parse.NS(html),
	parse.Node()
)
]]></prog>
</example>

<p>For further info about the arguments to the parsing functions, see the
documentation for
<pyref module="ll.xist.parse"><mod>ll.xist.parse</mod></pyref>.</p>
</section>

</section>


<section><h>Defining new elements and converting &xml; trees</h>

<p>To be able to parse an &xml; file, you have to provide an element class
for every element type that appears in the file. These classes either come from
modules provided by &xist; or you can define your own. Defining your own
element class for an element named <lit>cool</lit> works like this:</p>

<example><h>Defining a new element</h>
<prog>
class cool(xsc.Element):
	def convert(self, converter):
		node = html.b(self.content, " is cool!")
		return node.convert(converter)
</prog>
</example>

<p>You have to derive your new class from
<pyref module="ll.xist.xsc" class="Element"><class>xsc.Element</class></pyref>.
The name of the class will be the element name. For element type names that
are invalid Python identifiers, you can use the class attribute <lit>xmlname</lit>
in the element class to overwrite the element name.</p>
<p>To be able to convert an element of this type to a new &xml; tree
(probably &html; in most cases), you have to implement the
<pyref module="ll.xist.xsc" class="Node" method="convert"><meth>convert</meth></pyref>
method. In this method you can build a new &xml; tree from the content and attributes
of the object.</p>

<p>Using this new element is simple</p>

<example><h>Using the new element</h>
<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = cool("Python")</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.conv().bytes())</input>
b'&lt;b&gt;Python is cool!&lt;/b&gt;'
</tty>
</example>

<p><pyref module="ll.xist.xsc" class="Node" method="conv"><meth>conv</meth></pyref> simply
calls
<pyref module="ll.xist.xsc" class="Node" method="convert"><meth>convert</meth></pyref>
with a default <pyref module="ll.xist.xsc" class="Converter"><obj>converter</obj></pyref>
argument. We'll come to converters in a minute.
<pyref module="ll.xist.xsc" class="Node" method="bytes"><meth>bytes</meth></pyref>
is a method that converts the node to a byte string. This method will be explained
when we discuss the publishing interface.</p>

<p>Note that it is vital for your own <meth>convert</meth>
methods that you recursively call <meth>convert</meth>
on your own content, because otherwise some unconverted nodes
might remain in the tree. Let's define a new element:</p>
<prog>
class python(xsc.Element):
	def convert(self, converter):
		return html.a("Python", href="http://www.python.org/")
</prog>
<p>Now we can do the following:</p>
<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = cool(python())</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.conv().bytes())</input>
b'&lt;b&gt;&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; is cool!&lt;/b&gt;'
</tty>
<p>But if we forget to call
<pyref module="ll.xist.xsc" class="Node" method="convert"><meth>convert</meth></pyref>
for our own content, i.e. if the element <pyref class="cool"><class>cool</class></pyref>
was written like this:</p>
<prog>
class cool(xsc.Element):
	def convert(self, converter):
		return html.b(self.content, " is cool!")
</prog>
<p>we would get:</p>
<prog>
&gt;&gt;&gt; node = cool(python())
&gt;&gt;&gt; print(node.conv().bytes())
b'&lt;b&gt;&lt;python&gt;&lt;/python&gt; is cool!&lt;/b&gt;'
</prog>

<p>Furthermore <meth>convert</meth> should never modify <self/>, because
<meth>convert</meth> might be called multiple times for the same node.</p>

<section><h>Converters</h>
<p><pyref module="ll.xist.xsc" class="Node" method="conv"><meth>conv</meth></pyref>
is a convenience method that creates a default converter for you and calls
<pyref module="ll.xist.xsc" class="Node" method="convert"><meth>convert</meth></pyref>.
This converter is created once and is passed to all <meth>convert</meth>
calls. It is used to store parameters for the conversion process and it allows
<meth>convert</meth> methods to store additional information, so that it is
available elsewhere during the conversion process. You can also call
<pyref module="ll.xist.xsc" class="Node" method="convert"><meth>convert</meth></pyref>
yourself, which would look like this:</p>

<prog>
from ll.xist import xsc
from ll.xist.ns import html

node = cool(python())
node = node.convert(xsc.Converter())
</prog>

<p>You can pass the following arguments to the
<pyref module="ll.xist.xsc" class="Converter"><class>Converter</class></pyref> constructor:</p>
<dl>
<dt><obj>root</obj></dt><dd><obj>root</obj> (which defaults to <lit>None</lit>) is the root &url;
for the conversion process. When you want to resolve a link in some of your own <meth>convert</meth> methods,
the &url; must be interpreted relative to this root &url; (You can use
<pyref module="ll.xist.xsc" class="URLAttr" method="forInput"><meth>URLAttr.forInput</meth></pyref>
for that).</dd>
<dt><obj>mode</obj></dt><dd><obj>mode</obj> (which defaults to <lit>None</lit>) works the same way
as modes in &xslt;. You can use this for implementing different conversion modes.</dd>
<dt><obj>stage</obj></dt><dd><obj>stage</obj> (which defaults to <lit>"deliver"</lit>)
allows you to implement multi stage conversion: Suppose that you want to deliver a dynamically
constructed web page with &xist; that contains results from a database query and the current time.
The data in the database changes infrequently, so it doesn't make sense to do the query on
every request. The query is done every few minutes and the resulting &html; tree is
stored in the servlet (using any of the available Python servlet technologies).
For this conversion the <obj>stage</obj> would be <lit>"cache"</lit> and your database &xml;
element would do the query when <lit><obj>stage</obj>=="cache"</lit>. Your time display element
would do the conversion when <lit><obj>stage</obj>=="deliver"</lit> and simply returns itself
when <lit><obj>stage</obj>=="cache"</lit>, so it would still be part of the cached &xml; tree
and would be converted to &html; on every request.</dd>
<dt><obj>target</obj></dt><dd><obj>target</obj> (which defaults to
<pyref module="ll.xist.ns.html"><mod>ll.xist.ns.html</mod></pyref>) specifies what the output should be.
Values must be namespace modules (see below for an explanation of namespaces).</dd>
<dt><obj>lang</obj></dt><dd><p><obj>lang</obj> (which defaults to <lit>None</lit>) is the language
in which the result tree should be. This can be used in the <meth>convert</meth> method
to implement different conversions for different languages, e.g.:</p>
<prog>
class note(xsc.Element):
	def convert(self, converter):
		if converter.lang == "de":
			title = "Anmerkung"
		elif converter.lang == "en":
			title = "Note"
		else:
			title = "???"
		node = xsc.Frag(
			html.h1(title),
			html.div(self.content)
		)
		return node.convert(converter)
</prog>
</dd>
</dl>

<p>Additional arguments are passed when a converter is created in the context of
a <pyref module="ll.make"><mod>make</mod></pyref> script.</p>

</section>

<section><h>Attributes</h>
<p>Setting and accessing the attributes of an element works either via
a dictionary interface or by accessing the &xml; attributes as Python attributes
of the elements <lit>attrs</lit> attribute:</p>
<example>
<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = html.a("Python", href="http://www.python.org/")</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.bytes())</input>
b'&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;'
<prompt>&gt;&gt;&gt; </prompt><input>del node.attrs.href</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.bytes())</input>
b'&lt;a&gt;Python&lt;/a&gt;'
<prompt>&gt;&gt;&gt; </prompt><input>node.attrs["href"] = "http://www.python.org"</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.bytes())</input>
b'&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;'
</tty>
</example>

<p>All attribute values are instances of subclasses of the class
<pyref module="ll.xist.xsc" class="Attr"><class>Attr</class></pyref>.
Available subclasses are:</p>

<ul>
<li><pyref module="ll.xist.xsc" class="TextAttr"><class>TextAttr</class></pyref>, for normal text attributes;</li>
<li><pyref module="ll.xist.xsc" class="URLAttr"><class>URLAttr</class></pyref>, for attributes that are &url;s;</li>
<li><pyref module="ll.xist.xsc" class="BoolAttr"><class>BoolAttr</class></pyref>, for boolean attributes (for such an attribute
only its presence is important, it's value will always be the same as the attribute name when publishing);</li>
<li><pyref module="ll.xist.xsc" class="IntAttr"><class>IntAttr</class></pyref>, for integer attributes;</li>
<li><pyref module="ll.xist.xsc" class="ColorAttr"><class>ColorAttr</class></pyref>, for color attributes (e.g. <lit>#ffffff</lit>).</li>
</ul>

<p><class>IntAttr</class> and <class>ColorAttr</class> mostly serve as documentation
of the attributes purpose. Both classes have no added functionality.</p>

<p><pyref module="ll.xist.xsc" class="Attr"><class>Attr</class></pyref> itself is derived from
<pyref module="ll.xist.xsc" class="Frag"><class>Frag</class></pyref> so it is possible
to use all the sequence methods on an attribute.</p>

<p>Unset attributes will be treated like empty ones so the following is possible:</p>

<example>
<prog>
del node.attrs["spam"]
node.attrs["spam"].append("ham")
</prog>
</example>

<p>This also means that after <lit>del node.attrs["spam"][:]</lit> the attribute
will be empty again and will be considered to be unset.
Such attributes will be skipped when publishing.</p>

<p>The main purpose of this is to allow you to construct values conditionally
and then use those values as attribute values:</p>

<prog>
import random

if random.random() &lt; 0.5:
	class_ = None
else:
	class_ = "foo"

node = html.div("foo", class_=class_)
</prog>

<p>In 50% of the cases the generated <class>div</class> element will not
have a <lit>class</lit> attribute.</p>

<section><h>Defining attributes</h>

<p>When you define a new element you have to specify the attributes allowed
for this element. For this use the class attribute <lit>Attrs</lit>
(which must be a class derived from
<pyref module="ll.xist.xsc" class="Element.Attrs"><class>xsc.Element.Attrs</class></pyref>)
and define the attributes by deriving them from one of the existing attribute classes.
We could extend our example element in the following way:</p>

<example><h>Using attributes</h>
<prog>
class cool(xsc.Element):
	class Attrs(xsc.Element.Attrs):
		class adj(xsc.TextAttr): pass

	def convert(self, converter):
		node = xsc.Frag(self.content, " is")
		if "adj" in self.attrs:
			node.append(" ", html.em(self.attrs.adj))
		node.append(" cool!")
		return node.convert(converter)
</prog>
</example>

<p>and use it like this:</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = cool(python(), adj="totally")</input>
<prompt>&gt;&gt;&gt; </prompt><input>node.conv().bytes()</input>
&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; is &lt;em&gt;totally&lt;/em&gt; cool!
</tty>

</section>


<section><h>Default attributes</h>
<p>It is possible to define default values for attributes via
the class attribute <lit>default</lit>:</p>

<example><h>Defining default attributes</h>
<prog>
class cool(xsc.Element):
	class Attrs(xsc.Element.Attrs):
		class adj(xsc.TextAttr):
			default = "absolutely"

	def convert(self, converter):
		node = xsc.Frag(self.content, " is")
		if "adj" in self.attrs:
			node.append(" ", html.em(self.attrs.adj))
		node.append(" cool!")
		return node.convert(converter)
</prog>
</example>

<p>Now if we instantiate the class without specifying
<lit>adj</lit> we'll get the default:</p>

<example><h>Using default attributes</h>
<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = cool(python())</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.conv().bytes())</input>
b'&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; is &lt;em&gt;absolutely&lt;/em&gt; cool!'
</tty>
</example>

<p>If we want a <class>cool</class> instance without
an <lit>adj</lit> attribute, we can pass <lit>None</lit>
as the attribute value:</p>

<example><h>Removing default attributes</h>
<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = cool(python(), adj=None)</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.conv().bytes())</input>
b'&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; is cool!'
</tty>
</example>

</section>

<section><h>Allowed attribute values</h>
<p>It's possible to specify that an attribute has a fixed set of allowed
values. This can be done with the class attribute <lit>values</lit>. We could
extend our example to look like this:</p>

<example><h>Defining allowed attribute values</h>
<prog>
class cool(xsc.Element):
	class Attrs(xsc.Element.Attrs):
		class adj(xsc.TextAttr):
			default = "absolutely"
			values = ("absolutely", "totally", "very")

	def convert(self, converter):
		node = xsc.Frag(self.content, " is")
		if "adj" in self.attrs:
			node.append(" ", html.em(self.attrs.adj))
		node.append(" cool!")
		return node.convert(converter)
</prog>
</example>

<p>These values won't be checked when we create our <class>cool</class>
instance. Only when this node is parsed from a file will the warning
be issued. The warning will also be issued if we publish such a node,
but note that for warnings Python's warning framework is used,
so the warning will be printed only once (but of course
you can change that with <func>warnings.filterwarnings</func>):</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>node = cool(python(), adj="pretty")</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.bytes())</input>
/Users/walter/checkouts/LivingLogic.Python.xist/src/ll/xist/xsc.py:2368: \
IllegalAttrValueWarning: Attribute value 'pretty' not allowed for __main__:cool.Attrs.adj
  warnings.warn(IllegalAttrValueWarning(self))
b'&lt;cool adj="very"&gt;&lt;python /&gt;&lt;/cool&gt;'
</tty>

</section>

<section><h>Required attributes</h>
<p>Finally it's possible to specify that an attribute is required.
This again will only be checked when parsing or publishing. To specify that an
attribute is required simply add the class attribute <lit>required</lit>
with the value <lit>True</lit>. The attribute <lit>alt</lit> of the
class <pyref module="ll.xist.ns.html" class="img"><class>ll.xist.ns.html.img</class></pyref>
is such an attribute, so we'll get:</p>

<example><h>Missing required attributes</h>
<tty>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist.ns import html</input>
<prompt>&gt;&gt;&gt; </prompt><input>node = html.img(src="eggs.png")</input>
<prompt>&gt;&gt;&gt; </prompt><input>print(node.bytes())</input>
/Users/walter/checkouts/LivingLogic.Python.xist/src/ll/xist/xsc.py:2770: \
RequiredAttrMissingWarning: Required attribute 'alt' missing in ll.xist.ns.html:img.Attrs.
  warnings.warn(errors.RequiredAttrMissingWarning(self, attrs.keys()))
&lt;img src="eggs.png" /&gt;
</tty>
</example>

</section>

</section>

<section><h>Namespaces and pools</h>

<p>Now that you've defined your own elements, you have to tell the parser
about them, so they can be instantiated when a file is parsed. First you have to
assign an &xml; namespace to these classes. This is done by setting the class
attribute <lit>xmlns</lit> to the namespace name:</p>

<example><h>Assigning a namespace to elements</h>
<prog>
from ll.xist import xsc, parse
from ll.xist.ns import html

xmlns = "http://xmlns.example.org/foo"

class python(xsc.Element):
	xmlns = xmlns

	def convert(self, converter):
		return html.a("Python", href="http://www.python.org/")

class cool(xsc.Element):
	xmlns = xmlns

	def convert(self, converter):
		node = html.b(self.content, " is cool!")
		return node.convert(converter)
</prog>
</example>

<p>When parsing the parser fetches the classes it uses from a <class>Pool</class>
object. We can put our two classes into a pool like this:</p>

<example><h>Putting elements in a pool</h>
<prog>
pool = xsc.Pool(python, cool)
</prog>
</example>

<p>It's also possible to register the element classes in a pool directly at
class construction time via a <lit>with</lit> block like this:</p>

<example><h>Populating a pool with a <lit>with</lit> block</h>
<prog>
from ll.xist import xsc, parse
from ll.xist.ns import html

with xsc.Pool() as pool:
	xmlns = "http://xmlns.example.org/foo"

	class python(xsc.Element):
		xmlns = xmlns

		def convert(self, converter):
			return html.a("Python", href="http://www.python.org/")

	class cool(xsc.Element):
		xmlns = xmlns

		def convert(self, converter):
			node = html.b(self.content, " is cool!")
			return node.convert(converter)
</prog>
</example>

<p>Now you can use this pool for parsing:</p>

<example><h>Parsing &xml;</h>
<prog><![CDATA[
s = b'<cool xmlns="http://xmlns.example.org/foo"><python/></cool>'

node = parse.tree(s, parse.Expat(ns=True), pool)
]]></prog>
</example>

<p>It's also possible to call the parsing function with a predefined mapping
between namespace names and namespace prefixes:</p>

<example><h>Parsing &xml; with predefined prefix mapping</h>
<prog><![CDATA[
s = b'<cool><python/></cool>'

node = parse.tree(s, parse.Expat(), parse.NS("http://xmlns.example.org/foo"), pool)
]]></prog>
</example>

<p>If you have many elements, registering them in a pool becomes cumbersome.
In this case you can put your element classes into a module and then
register all elements in the module:</p>

<example><h>Registering modules in a pool</h>
<prog>
import foo_xmlns # This is the module containing the element classes

pool = xsc.Pool(foo_xmlns)
</prog>
</example>

</section>

<section><h>Global attributes</h>
<p>You can define global attributes belonging to a certain namespace by defining
a global <class>Attrs</class> class and giving each attribute a namespace name
via <lit>xmlns</lit>:</p>

<prog>
class Attrs(xsc.Attrs):
	class foo(xsc.TextAttr):
		xmlns = "http://www.example.com/foo"
</prog>

<p>To make this global attribute know to the parsing, you simply can put
the <class>Attrs</class> in the pool used for parsing.</p>

<p>Setting and accessing such an attribute can be done by using the
attribute class instead of the attribute name like this:</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist.ns import html</input>
<prompt>&gt;&gt;&gt; </prompt><input>node = html.div("foo", {Attrs.foo: "bar"})</input>
<prompt>&gt;&gt;&gt; </prompt><input>str(node[Attrs.foo])</input>
'bar'
</tty>

<p>An alternate way of specifying a global attribute in a constructor looks
like this:</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist.ns import html</input>
<prompt>&gt;&gt;&gt; </prompt><input>node = html.div("foo", Attrs(foo="baz"))</input>
<prompt>&gt;&gt;&gt; </prompt><input>str(node[Attrs.foo])</input>
'baz'
</tty>

</section>

<section><h>Entities</h>

<p>In the same way as defining new element types, you can define new entities.
The following example is from the module
<pyref module="ll.xist.ns.abbr"><mod>ll.xist.ns.abbr</mod></pyref>:</p>

<example><h>Defining new entities</h>
<prog>
from ll.xist import xsc
from ll.xist.ns import html

class html(xsc.Entity):
	def convert(self, converter):
		return html.abbr(
			"HTML",
			title="Hypertext Markup Language",
			lang="en"
		)
</prog>
</example>

<p>You can use this entity in your &xml; files like this:</p>

<example><h>Using the newly defined entity</h>
<prog>
&lt;cool adj="very"&gt;&amp;html;&lt;/cool&gt;
</prog>
</example>

</section>

<section><h>Processing instructions</h>
<p>Defining processing instructions works just like elements and entities.
Derive a new class from
<pyref module="ll.xist.xsc" class="ProcInst"><class>ll.xist.xsc.ProcInst</class></pyref>
and implement <pyref module="ll.xist.xsc" class="Node" method="convert"><meth>convert</meth></pyref>.
The following example implements a processing instruction that returns an
uppercase version of its content as a text node.</p>

<example><h>Defining new processing instructions</h>
<prog>
class upper(xsc.ProcInst):
	def convert(self, converter):
		return xsc.Text(self.content.upper())
</prog>
</example>

<p>It can be used in an &xml; file like this:</p>

<example><h>Using the newly defined processing instruction</h>
<prog>
&lt;cool&gt;&lt;?upper foo?&gt;&lt;/cool&gt;
</prog>
</example>

<p>There are namespaces containing processing instruction classes that don't
provide a <meth>convert</meth> method. These processing instruction objects
will then be published as &xml; processing instructions. One example is the
namespace <pyref module="ll.xist.ns.php"><mod>ll.xist.ns.php</mod></pyref>.</p>

<p>Other namespaces (like <pyref module="ll.xist.ns.jsp"><mod>ll.xist.ns.jsp</mod></pyref>)
contain processing instruction classes, but they will be published in a different
(not &xml; compatible) format. For example <lit>ll.xist.ns.jsp.expression("foo")</lit>
will be published as <lit>&lt;%= foo&gt;</lit>.</p>

</section>

</section>


<section><h>Publishing &xml; trees</h>

<p>After creating the &xml; tree and converting the tree
into its final output form, you have to write the resulting tree
to a file. This can be done with the publishing &api;. Three methods
that use the publishing &api; are
<pyref module="ll.xist.xsc" class="Node" method="iterbytes"><meth>iterbytes</meth></pyref>,
<pyref module="ll.xist.xsc" class="Node" method="bytes"><meth>bytes</meth></pyref>
and
<pyref module="ll.xist.xsc" class="Node" method="write"><meth>write</meth></pyref>.
<pyref module="ll.xist.xsc" class="Node" method="bytes"><meth>iterbytes</meth></pyref>
is a generator that will yield the complete 8-bit &xml; string in fragments.
<pyref module="ll.xist.xsc" class="Node" method="bytes"><meth>bytes</meth></pyref>
returns the complete 8-bit &xml; string.</p>

<p>Writing a node to a file can be done with the method
<pyref module="ll.xist.xsc" class="Node" method="write"><meth>write</meth></pyref>:</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist.ns import html</input>
<prompt>&gt;&gt;&gt; </prompt><input>node = html.div("äöü", html.br(), "ÄÖÜ")</input>
<prompt>&gt;&gt;&gt; </prompt><input>node.write(open("foo.html", "wb"), encoding="ascii")</input>
</tty>

<p>All these methods use the method
<pyref module="ll.xist.xsc" class="Node" method="publish"><meth>publish</meth></pyref> internally.
<pyref module="ll.xist.xsc" class="Node" method="publish"><meth>publish</meth></pyref> gets passed
an instance of <pyref module="ll.xist.xsc" class="Publisher"><class>ll.xist.xsc.Publisher</class></pyref>.</p>

<section><h>Specifying an encoding</h>
<p>You can specify the encoding with the parameter <obj>encoding</obj>
(with the encoding specified in an &xml; declaration being the default, if there
is no such declaration <lit>"utf-8"</lit> is used). Unencodable characters will
be escaped with character references when possible (i.e. inside text nodes, for
comments or processing instructions you'll get an exception):</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist import xsc</input>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist.ns import html</input>
<prompt>&gt;&gt;&gt; </prompt><input>s = "A\xe4\u03a9\u8a9e"</input>
<prompt>&gt;&gt;&gt; </prompt><input>node = html.div(s)</input>
<prompt>&gt;&gt;&gt; </prompt><input>node.bytes(encoding="ascii")</input>
<![CDATA[b'<div>;A&#228;&#937;&#35486;</div>;']]>
<prompt>&gt;&gt;&gt; </prompt><input>node.bytes(encoding="iso-8859-1")</input>
<![CDATA[b'<div>;A\xe4&#937;&#35486;</div>;']]>
<prompt>&gt;&gt;&gt; </prompt><input>xsc.Comment(s).bytes(encoding="ascii")</input>
Traceback (most recent call last):
<rep>...</rep>
  File "/Users/walter/.local/lib/python3.3/encodings/ascii.py", line 22, in encode
    return codecs.ascii_encode(input, self.errors)[0]
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-3: ordinal not in range(128)
</tty>

<p>When you include an <pyref module="ll.xist.ns.xml" class="XML">&xml; header</pyref>
or an <pyref module="ll.xist.ns.meta" class="contenttype">&html; meta header</pyref>,
&xist; will automatically insert the correct encoding when publishing:</p>

<tty>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist import xsc</input>
<prompt>&gt;&gt;&gt; </prompt><input>from ll.xist.ns import xml, meta</input>
<prompt>&gt;&gt;&gt; </prompt><input>e = xsc.Frag(xml.XML(), "\n", meta.contenttype())</input>
<prompt>&gt;&gt;&gt; </prompt><input>e.conv().bytes(encoding="iso-8859-15")</input>
<![CDATA[b'<?xml version="1.0" encoding="iso-8859-15"?>\n<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" />']]>
</tty>
</section>

<section><h>&html; compatibility</h>
<p>Another useful parameter is <obj>xhtml</obj>,
it specifies whether you want pure &html; or &xhtml; as output:</p>

<dl>
<dt><lit>xhtml==0</lit></dt><dd>This will give you pure &html;, i.e. no
final <lit>/</lit> for elements with an empty content model, so you'll get e.g.
<markup>&lt;br&gt;</markup> in the output. Elements that don't have an empty
content model, but are empty will be published with a start and end tag
(i.e. <markup>&lt;div&gt;&lt;/div&gt;</markup>).</dd>
<dt><lit>xhtml==1</lit></dt><dd>This gives &html; compatible &xhtml;.
Elements with an empty content model will be published like this:
<markup>&lt;br /&gt;</markup> (This is the default).</dd>
<dt><lit>xhtml==2</lit></dt><dd>This gives full &xml; output. Every empty
element will be published with an empty tag (without an additional space):
<markup>&lt;br/&gt;</markup> or <markup>&lt;div/&gt;</markup>.</dd>
</dl>
</section>

<section><h>Namespaces</h>

<p>By default &xist; doesn't output any namespace declarations. The simplest
way to change that, is to pass <lit>True</lit> for the <obj>prefixdefault</obj>
argument when publishing:</p>

<example><h>Publishing namespace info</h>
<prog>
from ll.xist.ns import html

e = html.html(
	html.head(
		html.title("The page")
	),
	html.body(
		html.h1("The header"),
		html.p("The content")
	)
)

print(e.bytes(prefixdefault=True))
</prog>
</example>

<p>Using <lit>True</lit> allows &xist; to choose its own prefixes. The code
above will output (rewrapped for clarity):</p>
<prog><![CDATA[
<ns:html xmlns:ns="http://www.w3.org/1999/xhtml">
<ns:head><ns:title>The page</ns:title></ns:head>
<ns:body><ns:h1>The header</ns:h1><ns:p>The content</ns:p></ns:body>
</ns:html>
]]></prog>

<p>You can also use a fixed prefix:</p>

<prog>
print e.bytes(prefixdefault="h")
</prog>

<p>This will output (again rewrapped):</p>
<prog><![CDATA[
<h:html xmlns:h="http://www.w3.org/1999/xhtml">
<h:head><h:title>The page</h:title></h:head>
<h:body><h:h1>The header</h:h1><h:p>The content</h:p></h:body>
</h:html>]]></prog>

<p>If you want the empty prefix you can use <lit>None</lit>:</p>

<prog>
print e.bytes(prefixdefault=None)
</prog>

<p>This will output (again rewrapped):</p>
<prog><![CDATA[
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>The page</title></head>
<body><h1>The header</h1><p>The content</p></body>
</html>]]></prog>

<p>When elements from more than one namespace are present in the tree,
<obj>prefixdefault</obj> is unreliable. The first namespace encountered will
get the prefix specified by <obj>prefixdefault</obj>, all others will get a
different prefix. &xist; will never use the same prefix for different namespaces.
&xist; will also refuse to use an empty prefix for global attributes:</p>

<example><h>Publishing global attributes</h>
<prog>
from ll.xist import xsc
from ll.xist.ns import html, xlink

with xsc.build():
	with html.html() as e:
		with html.head():
			+html.title("The page")
		with html.body():
			+html.h1("The header"),
			with html.p():
				+xsc.Text("The "),
				+html.a(
					"Python",
					xlink.Attrs(
						href="http://www.python.org/",
						title="Python",
						type="simple"
					),
					href="http://www.python.org/")
				+xsc.Text(" homepage")

print e.bytes(prefixdefault=None)
</prog>
</example>

<p>This will output:</p>

<prog><![CDATA[
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ns="http://www.w3.org/1999/xlink">
<head><title>The page</title></head>
<body>
<h1>The header</h1>
<p>The <a ns:href="http://www.python.org/" ns:type="simple" ns:title="Python" href="http://www.python.org/">Python</a> homepage</p>
</body>
</html>]]>
</prog>

<p>In the case of multiple namespaces you can use the <obj>prefixes</obj>
argument to specify an explicit prefix for each namespace. So we could change
the publishing statement from our example above to:</p>

<prog>
print(e.bytes(prefixes={"http://www.w3.org/1999/xhtml": None, "http://www.w3.org/1999/xlink": "xl"}))
</prog>

<p>which would give us the output:</p>

<prog><![CDATA[
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xl="http://www.w3.org/1999/xlink">
<head><title>The page</title></head>
<body>
<h1>The header</h1>
<p>The <a xl:href="http://www.python.org/" xl:type="simple" xl:title="Python" href="http://www.python.org/">Python</a> homepage</p>
</body>
</html>]]>
</prog>

<p>Note that we can shorten the publishing call from above to:</p>

<prog>
print(e.bytes(prefixes={html.xmlns: None, xlink.xmlns: "xl"}))
</prog>

<p>or even to:</p>

<prog>
print(e.bytes(prefixes={html: None, xlink: "xl"}))
</prog>

<p>Furthermore it's possible to suppress output of namespace declarations
for certain namespaces by using the <obj>hidexmlns</obj> argument:</p>

<prog>
print(e.bytes(prefixes={html: None, xlink: "xl"}, hidexmlns=(html, xlink)))
</prog>

<p>This will output:</p>
<prog><![CDATA[
<html>
<head><title>The page</title></head>
<body>
<h1>The header</h1>
<p>The <a xl:href="http://www.python.org/" xl:type="simple" xl:title="Python" href="http://www.python.org/">Python</a> homepage</p>
</body>
</html>
]]></prog>


<p>Finally it's possible to force the output of namespace declarations
for certain namespaces (even if elements from those namespaces are not in the
tree) by using the <obj>showxmlns</obj> argument:</p>

<prog>
print html.div().bytes(prefixes={html: None, xlink: "xl"}, showxmlns=(xlink,))
</prog>

<p>This will output:</p>
<prog><![CDATA[<div xmlns="http://www.w3.org/1999/xhtml" xmlns:xl="http://www.w3.org/1999/xlink"></div>]]></prog>

</section>
</section>
</spc:wrap>
