                   Migration and modernization guide
                   =================================

Migrating to version 2.15
=========================

  Changes to plain text conversion
  --------------------------------

   The node method asText has been moved to the html namespace, so
   you have to replace:

 print node.asText()

   with:

 from ll.xist.ns import html
 print html.astext(node)

  Changes to htmlspecials.pixel
  -----------------------------

   If you've been using the color attribute for htmlspecials.pixel,
   you have to add a # in from of the value, as it is a CSS color
   value now. (And if've you've been using color and a CSS padding of
   a different color: This will no longer work).

  Migrating to version 2.14
  -------------------------

    Changes to presenters
    ---------------------

   Presenters work differently now. Instead of:

 print node.asrepr(presenters.CodePresenter)

   simply do the following:

 print presenters.CodePresenter(node)

  Migrating to version 2.13
  -------------------------

    Changes to ll.xist.xsc
    ----------------------

   xsc.Namespace.tokenize no longer has an encoding argument, but
   operates on a unicode string directly. You can either use the
   result of a asString call or decode the result of an asBytes call
   yourself.

  Migrating to version 2.11
  -------------------------

    Changes to ll.xist.xsc
    ----------------------

   The function ToNode has been renamed to tonode.

   ll.xist.Context no longer subclasses list. If you need a stack for
   your context, simply add the list as an attribute of the context
   object.

    Code rearrangements
    -------------------

   The iterator stuff from ll.xist.xfind has been moved to the ll
   package/module, i.e. you have to use ll.first instead of
   ll.xist.xfind.first.

    Changes to the walk method
    --------------------------

   The walk method has changed again. There are no inmodes and
   outmodes any longer. Instead input and output are Cursor objects.
   If you're using your own walk filters, you have to update them.
   For different output modes you can use the methods walknode,
   walkpath or walkindex instead of using the cursor yielded by walk.

   The node methods find and findfirst have been removed. Use
   xsc.Frag(node.walk(...) or node.walk(...)[0] instead.

    Changes to publishing
    ---------------------

   Publishing has changed: If you've used the method repr before to
   get a string representation of an XML tree, you have to use asrepr
   instead now (repr is a generator which will produce the string in
   pieces).

    Changes to the xfind module
    ---------------------------

   The functions item, first, last, count and iterone as well as the
   class Iterator have been moved to the ll module.

    Migrating to version 2.10
    -------------------------

      Changes to publishing
      ---------------------

   Publishing has been changed from using a stream API to using a
   iterator API. If you've been using Publisher.write or
   Publisher.writetext (in your own publish methods) you must update
   your code by replacing publisher.write(foo) with yield
   publisher.encode(foo) and publisher.writetext(foo) with yield
   publisher.encodetext(foo).

      Changes to the test suite
      -------------------------

   The test suite now uses py.test, so if you want to run it you'll
   need py.test.

      Changes to ll.xist.ns.code
      --------------------------

   The code in a ll.xist.ns.code.pyexec object is no longer executed
   at construction time, but at conversion time. So if you relied on
   this fact (e.g. to make a namespace available for parsing the rest
   of the XML file) you will have to change your code.

      Removed namespaces
      ------------------

   The namespace modules ll.xist.ns.css and ll.xist.ns.cssspecials
   have been removed.

    Migrating to version 2.9
    ------------------------

      Changes to exceptions
      ---------------------

   All exception classes have been moved from ll.xist.errors to
   ll.xist.xsc.

      Changes to XML name handling
      ----------------------------

   The class attribute xmlname no longer gets replaced with a tuple
   containing both the Python and the XML name. If you want to get
   the Python name, use foo.__class__.__name__.

      Changes to the methods walk, find and findfirst
      -----------------------------------------------

   The argument filtermode has been renamed to inmode and (for walk)
   walkmode has been renamed to outmode.

    Migrating to version 2.8
    ------------------------

      Changes to display hooks
      ------------------------

   The way XIST uses sys.displayhook has been enhanced. To make use
   of this, you might want to update your Python startup script. For
   more info see the installation instructions.

      Changes to the xmlns attribute
      ------------------------------

   Each element (or entity, or processing instruction) class had an
   attribute xmlns that references the namespace module. This
   attribute has been renamed to __ns__.

      Other minor changes
      -------------------

   ll.xist.ns.specials.x has been renamed to
   ll.xist.ns.specials.ignore.

   ll.xist.xfind.item no longer handles slices. If you've used that
   functionality, you may now use slices on XFind operators, and
   materilize the result, i.e. replace xfind.slice(foo, 1, -1) with
   list(foo[1:-1]), if foo is an XFind operator. Otherwise you can
   use list(foo)[1:-1]

    Migrating to version 2.7
    ------------------------

      Changes to ll.xist.xfind
      ------------------------

   The functions xfind.first and xfind.last now use xfind.item, so
   they will raise an IndexError when no default value is passed. To
   get the old behaviour, simply pass None as the default.

    Migrating to version 2.6
    ------------------------

      Changes to the publishing API
      -----------------------------

   The top level publishing method in the publisher has been renamed
   from dopublication to publish. If you're using the publishing API
   directly (instead of the node methods asBytes and write), you'll
   have to update your code.

   The method that writes a unicode object to the output stream has
   been renamed from publish to write. This is only relevant when
   you've overwritten the publish method in your own node class (e.g.
   in JSP tag library directives or similar stuff, or for special
   nodes that publish some text literally).

      Changes to the presentation API
      -------------------------------

   The presentation API has been changed too: The top level
   presentation method in the presenter has been renamed from
   dopresentation to present. This is only relevant if you've written
   your own presenter, or are using the presentation API directly
   (instead of the node method repr).

      Parsing HTML
      ------------

   Parsing HTML is now done via libxml2's HTML parser, instead of
   using µTidyLib of mxTidy. You can no longer pass arguments to
   tidy. Only the boolean values of the tidy argument will be used.
   There are no other visible changes to the API but the result of
   parsing might have changed.

      Removed APIs and scripts
      ------------------------

   The script xscmake.py has been removed.

   The visit method has been removed.

   ll.xist.xsc.FindOld has been removed.

   ll.xist.ns.xml.header has been renamed to
   ll.xist.ns.xml.declaration.

    Migrating to version 2.5
    ------------------------

      Changes to content model
      ------------------------

   The boolean class attribute empty for element classes has been
   replaced by an object model. empty is still supported, but issues
   a PendingDeprecationWarning. If you don't want to specify a proper
   content model for your own elements you can replace empty = False
   with model = True (which is a shortcut for model = sims.Any()) and
   empty = True with model = False (which is a shortcut for model =
   sims.Empty()).

    Migrating to version 2.4
    ------------------------

      Changes to parsing
      ------------------

   Parsing has changed internally, but the module level parsing
   functions in ll.xist.parsers are still available (and will create
   a parser on the fly), but a few arguments have changed:

   handler
           This argument is no longer available, if you need a
           special handler, you have to subclass
           ll.xist.parsers.Parser and call its parsing methods.

   parser
           This argument has been renamed to saxparser and is not a
           SAX2 parser instance any longer, but a callable that will
           create a SAX2 parser.

   sysid
           sysid is now available for all parsing functions not just
           parseString.

      Changes to converter contexts
      -----------------------------

   ll.xist.converters.Converter.__getitem__ now doesn't use the key
   passed in, but key.Context as the real dictionary key. This has
   the following consequences:

     * If you want a unique context for your own element class, you
       must implement a new Context class (otherwise you'd get
       ll.xist.xsc.Element.Context):

 class Foo(xsc.Element):
    empty = False

    class Context(xsc.Element.Context):
       def __init_(self):
          xsc.Element.Context.__init__(self)
          ...

     * Subclasses that don't overwrite Context (as well as instances
       of those classes) can be passed to
       ll.xist.converters.Converter.__getitem__ and the unique base
       class context object will be returned.

      Changed namespaces
      ------------------

   The character reference classes from ll.xist.ns.ihtml that are
   duplicates of those in ll.xist.ns.chars have been removed, so you
   have to use ll.xist.ns.chars for those characters in addition to
   ll.xist.ns.ihtml

    Migrating to version 2.3
    ------------------------

      Changes in namespace handling
      -----------------------------

   Namespace handling has changed. There are no entity or processing
   instruction prefixes any longer and creating a proper Prefixes
   object has been simplified. For example:

 prefixes = xsc.Prefixes()
 prefixes.addElementPrefixMapping(None, html)
 prefixes.addElementPrefixMapping("svg", svg)

   can be simplified to:

 prefixes = xsc.Prefixes(html, svg=svg)

   The three arguments elementmode, entitymode and procinstmode for
   the publishing methods have been combined into prefixmode, which
   is used for elements only.

      Changed namespaces
      ------------------

   The character reference classes from ll.xist.ns.html have been
   moved to a separate namespace ll.xist.ns.chars.

   The processing instructions eval_ and exec_ from the
   ll.xist.ns.code module have been renamed to pyeval and pyexec.

      Changed method names
      --------------------

   The method names beginPublication, endPublication and
   doPublication have been lowercased.

    Migrating to version 2.2
    ------------------------

      Attribute methods
      -----------------

   The Element methods for accessing attributes have been deprecated.
   So instead of node.hasattr("attr"), you should use:

 "attr" in node.attrs

   The same holds for checking whether an attribute is allowed. You
   can use the following code:

 "attr" in node.Attrs

   or:

 "attr" in NodeClass.Attrs

   or:

 NodeClass.isallowed("attr")

   Many Attrs methods have gained an additional parameter xml, which
   specifies whether an attribute name should be treated as the XML
   or the Python name of the attribute. Make sure that you're not
   mixing up your arguments in the function call. The safest method
   for this is using keyword arguments, e.g.:

 node.attr.get("attr", default=42)

      JSP directive page element
      --------------------------

   A contentType attribute is no longer generated for the
   ll.xist.ns.jsp.directive_page. You have to explicitely use an
   attribute contentType="text/html" to get a contentType attribute
   in the resulting JSP. The charset option is generated
   automatically from the encoding specified in the publisher.

      autoimg changes
      ---------------

   ll.xist.htmlspecials.autoimg will no longer touches existing width
   or height attributes, so e.g. setting the width to twice the image
   size via width="2*%(width)s" no longer works. You have to
   implement your own version of autoimg if you need this.

      find changes
      ------------

   find has been completely rewritten to use the new tree traversal
   filters. For backwards compatibility a filter functor
   ll.xist.xsc.FindOld exists that takes the same arguments as the
   old find method. I.e. you can replace:

 node.find(
    type=html.a,
    attr={"href": None},
    searchchildren=True
 )

   with:

 node.find(
    xsc.FindOld(
       type=html.a,
       attr={"href": None},
       searchchildren=True
    ),
    skiproot=True
 )

   But one minor difference remains: when skiproot is set to true in
   the new find method, the attributes of the root element will not
   be traversed. With the old method they would be traversed.

      doc changes
      -----------

   programlisting has been renamed to prog.

      Namespace changes
      -----------------

   Namespaces can no longer be instantiated. Instead you have to
   derive a class from Namespace. The xmlprefix argument from the
   constructor becomes a class attribute xmlname and the argument
   xmlname becomes xmlurl.

   Adding element classes to the namespace is now done with the
   Namespace classmethod update. If you want the turn a namespace
   into a module, you can use the classmethod makemod instead of
   update.

 xmlns = xsc.Namespace("foo", "http://www.foo.com/", vars()

 class xmlns(xsc.Namespace):
    xmlname = "foo"
    xmlurl = "http://www.foo.com/"
 xmlns.makemod(vars())

    Migrating to version 2.1
    ------------------------

     * The method withSep has been renamed to withsep.
     * The argument defaultEncoding for the various parsing functions
       has been renamed to encoding.

    Migrating to version 2.0
    ------------------------

      Attribute handling
      ------------------

   The biggest change is in the way attributes are defined. In older
   versions you had to define a class attribute attrHandlers that
   mapped attribute names to attribute classes. This created problems
   with "illegal" attribute names (e.g. class and http-equiv in
   HTML), so for them an ugly workaround was implemented. With 2.0
   this is no longer neccessary. Defining attributes is done via a
   class Attrs nested inside the element class like this:

 class foo(xsc.Element):
    class Attrs(xsc.Element.Attrs):
       class bar(xsc.TextAttr)
          "The bar attribute"
          default = "spam"
          values = ("spam", "eggs")
          required = True
       class baz(xsc.URLAttr):
          "The baz attribute"

   Default values, set of allowed attributes values and whether the
   attribute is required can be defined via class attributes as shown
   above. You should (directly or indirecty) inherit from
   xsc.Element.Attrs, because this class implements handling of
   global attributes. If you want to inherit some attributes (e.g.
   from your base class), you can derive from the appropriate Attrs
   class. Removing an attribute you inherited can be done like this:

 class bar(foo):
    class Attrs(foo.Attrs):
       baz = None

   This removes the attribute baz inherited from foo.

   For attribute names that are no legal Python identifiers, the same
   method can be used as for element classes: Define the real XML
   name via a class attribute. This class attribute has been renamed
   from name to xmlname.

   This also means that you always have to use the Python name when
   using attributes now. The XML name will only be used for parsing
   and publishing.

   XIST 2.0 tries to be as backwards compatible as possible: An
   existing attrHandlers attribute will be converted to an Attrs
   class on the fly (and will generate a DeprecationWarning when the
   class is created). An Attrs class will automatically generate an
   attrHandlers attribute, so it's possible to derive from new
   element classes in the old way. The only situation where this
   won't work, is with attributes where the Python and XML name
   differ, you have to use "new style" attributes there.

      Namespace support
      -----------------

   XIST supports XML namespaces now and for parsing it's possible to
   configure which namespaces should be available for instantiating
   classes from. For more info about this refer to the documentation
   for the class Prefixes.

   Before 2.0 the XML name for a namespace object was pretty useless,
   now it can be used as the namespace name in xmlns attributes and
   it will be used for that when publishing and specifying an
   elementmode of 2 in the call to the publishing method or the
   constructor of the publisher.

   Namespace objects should now be named xmlns instead of namespace
   as before.

      Global attributes
      -----------------

   Global attributes are supported now, e.g. the attributes xml:lang
   and xml:space can be specified in an element constructor like
   this:

 from ll.xist import xsc
 from ll.xist.ns import html, xml

 node = html.html(
    content,
    {(xml, "lang"): "en", (xml, "space"): "preserve"},
    lang="en"
 )

   Instead of the module object (which must contain a namespace
   object named xmlns), you can also pass the namespace object itself
   (i.e. xml.xmlns) or the namespace name (i.e.
   "http://www.w3.org/XML/1998/namespace").

      Namespace changes
      -----------------

   The classes XML and XML10 have been moved from ll.xist.xsc to
   ll.xist.ns.xml.

   All the classes in ll.xist.ns.specials that are specific to HTML
   generation have been moved to the new module
   ll.xist.ns.htmlspecials.

   The module ll.xist.ns.html has been updated to the XHTML
   specification, so there might be some changes. The new feature for
   specifying attribute restrictions has been used, so e.g. you'll
   get warnings for missing alt attributes in img elements. These
   warnings are issued via the warning framework. Refer to the
   documentation for the warnings module to find out how to configure
   the handling of these warnings.

      Miscellaneous
      -------------

   XIST now requires at least Python 2.2.1 because the integer
   constants True and False are used throughout the code wherever
   appropriate. These constants will become instances of the new
   class bool in Python 2.3. You might want to change your code too,
   to use these new constant (e.g. when setting the element class
   attribute empty).

   Using mixed case method names was a bad idea, because this
   conflicts with Python's convention of using all lowercase names
   (without underscores). These method names will be fixed in the
   next few XIST versions. The first names that where changed were
   the element methods getAttr and hasAttr, which have been renamed
   to getattr and hasattr respectively. getAttr and hasAttr are still
   there and can be called without generating DeprecationWarnings,
   but they will start to generate warnings in the upcoming versions.