NAME
    XML::LibXML::Augment - extend XML::LibXML::{Attr,Element,Document} on a
    per-namespace/element basis

SYNOPSIS
     {
       package Local::Element::Bar;
   
       use 5.010;
       use strict;
       use XML::LibXML::Augment -names => ['{http://example.com/}bar'];
   
       sub tellJoke
       {
         say q{A man walked into a bar.};
         say q{"Ouch," he said.};
         say q{It was an iron bar.};
       }
     }
 
     {
       package main;
   
       use 5.010;
       use strict;
       use XML::LibXML::Augment;
   
       my $doc = XML::LibXML->load_xml(string => <<'XML');
       <foo xmlns="http://example.com/">
         <bar baz="1" />
       </foo>
       XML
   
       XML::LibXML::Augment->upgrade($doc);
       $doc->findnodes('//*[@baz]')->shift->tellJoke;
     }

DESCRIPTION
    XML::LibXML is super-awesome. However, I don't know about you, but
    sometimes I wish it had some domain-specific knowledge. For example, if
    I have an XML::LibXML::Element which represents an HTML "<form>"
    element, why can't it have a "submit" method?

    OK, so I can subclass XML::LibXML::Element, but then I call "childNodes"
    on my subclass, and get back plain, non-subclassed objects, and I'm back
    where I first began.

    XML::LibXML::Augment is the package I've been meaning to write for quite
    some time, to take care of all those issues.

    The magic is in the import method. You write a package which imports
    XML::LibXML::Augment with particular settings. Then, once you've parsed
    the document, you call "XML::LibXML::Augment->upgrade" on the root node.

  "import %args"
    Currently three options are supported. Each has a leading hyphen.

   "-names => \@list"
    Each item on the list is the name of an element you want to override. If
    the element is in a namespace, use Clark notation:

     {http://www.example.com/namespace}localname

    If the element is not in a namespace, then leave out the curly braces.
    Because of clashes (see "Conflict resolution" in CAVEATS below) it seems
    like a bad idea to try to augment non-namespaced elements based entirely
    on their localname. But, hey, you want to do it? It's your funeral.

    You can use "*" as the localname to indicate that you wish to subclass
    all elements in a particular namespace. (Again, see "Conflict
    resolution".)

    Yes, this is a list, because it might make sense to use the same package
    to cover, say, HTML "<a>", "<link>" and "<area>" elements.

   "-type => $type"
    $type can be either 'Element', 'Attr' or 'Document', but defaults to
    'Element'. This indicates what sort of thing you're subclassing. Only
    elements, attributes and documents are supported. (Document subclassing
    is based on the namespace and localname of its root element.)

    Elements, attributes and documents are pairwise disjoint classes, so you
    cannot (for example) subclass elements and attributes in the same
    package.

   "-isa => \@packages"
    Normally the import routine will automatically establish your package as
    a subclass of XML::LibXML::Augment::Attr or
    XML::LibXML::Augment::Element by monkeying around with your @ISA.

    There are times when you want more precise control over @ISA though,
    such as inheritance heirarchies:

      Local::HTML::TableHeader
         -> Local::HTML::TableCell
            -> Local::HTML::Element
               -> XML::LibXML::Augment::Element

    In this case, you probably want to use the automatic subclassing for
    Local::HTML::Element, but not for the other two classes, which would
    work better with explicit subclassing:

     {
       package Local::HTML::TableCell;
       use XML::LibXML::Augment
         -names => ['{http://www.w3.org/1999/xhtml}td'],
         -isa   => ['Local::HTML::Element'];
     }

  "upgrade(@things)"
    This is a function, not a method. It's not exported, so call it with its
    full name:

     XML::LibXML::Augment::upgrade(@things);

    Upgrades the things in-place, skipping over things that cannot be
    upgraded, and returns the things as a list. You can of course call it
    like this:

     @upgraded = XML::LibXML::Augment->upgrade(@things);

    But bear in mind that because of the way Perl method calls work, this is
    effectively the same as:

     @upgraded = (
       'XML::LibXML::Augment',
       XML::LibXML::Augment::upgrade(@things),
       );

    What is upgrading? Things that are not blessed objects are not
    upgradable. Blessed objects that XML::LibXML::Augment can find an
    appropriate subclass for are reblessed into that package (e.g.
    XML::LibXML::Comment is reblessed into XML::LibXML::Augment::Comment).
    The nodes in XML::LibXML::NodeLists are reblessed.

  "rebless($thing)"
    This is basically a single-argument version "upgrade" but designed to be
    called as a class method, and doesn't recurse into nodelists.

      my $upgraded = XML::LibXML::Augment->rebless($element);

    Note that $element is actually upgraded in-place.

      refaddr($upgraded) == refaddr($element); # true

  "ideal_class_for_object($object)"
    Calculates the class that "rebless" would bless the object into, but
    doesn't actually do the reblessing.

  "make_class(@superclasses)"
    Constructs a new class that is a subclass of the given classes. Call
    this as a class method. Returns the class name. This is a method used
    internally by XML::LibXML::Augment, documented in case anybody else
    wants to use it.

  "BLESS"
    XML::LibXML::Augment doesn't actually have a method called "BLESS", but
    your package can do.

    Inspired by Moose's "BUILD" method, your package's "BLESS" method will
    be called (if it exists) just after an XML::LibXML node is reblessed
    into your package. Unlike Moose's "BUILD" method, the inheritance chain
    isn't automatically walked. It is your package's responsibility to call
    "SUPER::BLESS" if required.

    Do bear in mind that XML::LibXML's node objects are little more than
    pointers to the "real" XML nodes that live on the C side of the XS
    divide. As such, XML::LibXML can (and frequently does) destroy and
    re-instantiate the pointers willy-nilly. This may limit the usefulness
    of "BLESS".

HOW DOES IT WORK?
    Mostly just careful use of inheritance.

CAVEATS
  Conflict resolution
    Only one class can handle any given element. If two different modules
    want to subclass, say, XHTML "<form>" elements, there can be only one
    winner. So, which one wins? Neither. XML::LibXML::Augment creates a
    brand, spanking new class which inherits from both, and that new class
    wins. This will usually work, but may trip up sometimes. The "joke.pl"
    example bundled with the XML-LibXML-Augment release gives a
    demonstration of this feature.

    Note that packages which use an element wildcard, for instance:

     package Local::HTML::Element;
     use XML::LibXML::Augment -names => ['{http://www.w3.org/1999/xhtml}*'];

    are treated purely as fallbacks. If there exists a non-wildcard class to
    handle an element, then the wildcard class will be ignored altogether -
    it won't be included in the funky on-the-fly class generation described
    above.

    For these reasons, wildcards are perhaps best avoided. It's usually
    better to do something like:

     package Local::HTML::Element;
     our @ELEMENTS;
     BEGIN {
       @ELEMENTS = map { "{http://www.w3.org/1999/xhtml}$_" }
         qw/a area b col colgroup ... u/;
     }
     use XML::LibXML::Augment -names => \@ELEMENTS;

  XML::LibXML::XPathContext
    We don't touch XML::LibXML::XPathContext. Results from calling, e.g.
    "findnodes" on an XPath context will return plain old XML::LibXML nodes.
    (You can of course upgrade them.) That doesn't render XPath completely
    unusable though - XML::LibXML::Node also has a "findnodes" method, which
    will return upgraded objects.

  Subclassing all elements (or all attributes)
    XML::LibXML::Augment requires you to specify the namespace URI and
    localname of the elements/attributes you wish to subclass. If you want
    to provide additional methods to all XML::LibXML::Elements, then perhaps
    XML::LibXML::Augment is not for you. Try:

     sub XML::LibXML::Element::myAwesomeMethod {
       ...
     }

    If you think adding methods to other peoples' classes is evil, then go
    write some Java and quit complaining.

BUGS
    Please report any bugs to
    <http://rt.cpan.org/Dist/Display.html?Queue=XML-LibXML-Augment>.

SEE ALSO
    XML::LibXML.

AUTHOR
    Toby Inkster <tobyink@cpan.org>.

COPYRIGHT AND LICENCE
    This software is copyright (c) 2012 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

