POE-Filter-XML

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for POE-Filter-XML: 1.140700

1.140700  2014-03-11 22:58:37 Europe/Amsterdam
        Remove all bullshit related to MooseX::Declare
        Fix annoying bug in toString picking up Moose attributes


1.102960  2010-10-23 01:35:46 America/Chicago
        Fix issues with not_streaming
        Deprecation warning for ALL CAPS parameters improved
        Add a test for the not_streaming functionality
        Clean up some trailing whitespace

1.102800  2010-10-07 03:08:23 America/Chicago
        Overhaul internals to use MooseX::Declare
        Remove Utils.pm (No one should be using it)
        Redo documentation using Pod::Weaver
        Remove all 5.10isms (should be clean wherever MXD runs)
        Distribution now controlled by Dist::Zilla

2009-04-18 NPEREZ <nperez@cpan.org>

lib/POE/Filter/XML.pm  view on Meta::CPAN

has parser =>
(
    is => 'ro',
    isa => 'XML::LibXML',
    lazy => 1,
    builder => '_build_parser',
    clearer => '_clear_parser'
);


has not_streaming =>
(
    is => 'ro',
    isa => 'Bool',
    default => 0,
);

sub _build_handler {
    my ($self) = @_;
    POE::Filter::XML::Handler->new(not_streaming => $self->not_streaming)
}

sub _build_parser {
    my ($self) = @_;
    XML::LibXML->new(Handler => $self->handler)
}


sub BUILD {
    my ($self) = @_;

lib/POE/Filter/XML.pm  view on Meta::CPAN

            or do
            {
                my $err = $@ || 'Zombie error';
                $self->callback->($err);
            };

            if($self->handler->has_finished_nodes())
            {
                my $node = $self->handler->get_finished_node();

                if($node->stream_end() or $self->not_streaming)
                {
                    $self->parser->parse_chunk('', 1);
                    $self->reset();
                }

                return [$node];
            }
        }
        return [];
    }

lib/POE/Filter/XML.pm  view on Meta::CPAN


=head1 DESCRIPTION

POE::Filter::XML provides POE with a completely encapsulated XML parsing
strategy for POE::Wheels that will be dealing with XML streams.

The parser is XML::LibXML

=head1 PUBLIC_ATTRIBUTES

=head2 not_streaming

    is: ro, isa: Bool, default: false

Setting the not_streaming attribute to true via new() will put this filter into
non-streaming mode, meaning that whole documents are parsed before nodes are
returned. This is handy for XMLRPC or other short documents.

=head1 PRIVATE_ATTRIBUTES

=head2 buffer

    is: ro, isa: ArrayRef, traits: Array

buffer holds the raw data to be parsed. Raw data should be split on network
new lines before being added to the buffer. Access to this attribute is

lib/POE/Filter/XML.pm  view on Meta::CPAN

generated while parsing content. By default it holds a CodeRef that simply
calls Carp::confess.

=head2 handler

    is: ro, isa: POE::Filter::XML::Handler

handler holds the SAX handler to be used for processing events from the parser.
By default POE::Filter::XML::Handler is instantiated and used.

The L</not_streaming> attribute is passed to the constructor of Handler.

=head2 parser

    is: ro, isa: XML::LibXML

parser holds an instance of the XML::LibXML parser. The L</handler> attribute
is passed to the constructor of XML::LibXML.

=head1 PUBLIC_METHODS

lib/POE/Filter/XML.pm  view on Meta::CPAN


=head1 PROTECTED_METHODS

=head2 reset

reset() is an internal method that gets called when either a stream_start(1)
POE::Filter::XML::Node gets placed into the filter via L</put>, or when a
stream_end(1) POE::Filter::XML::Node is pulled out of the queue of finished
Nodes via L</get_one>. This facilitates automagical behavior when using the
Filter within the XMPP protocol that requires many new stream initiations.
This method is also called after every document when not in streaming mode.
Useful for handling XMLRPC processing.

This method really should never be called outside of the Filter, but it is
documented here in case the Filter is used outside of the POE context.

=head1 PRIVATE_METHODS

=head2 BUILD

A BUILD method is provided to parse the initial buffer (if any was included

lib/POE/Filter/XML/Handler.pm  view on Meta::CPAN

    clearer => '_clear_depth_stack',
    handles =>
    {
        push_depth_stack => 'push',
        pop_depth_stack => 'pop',
        depth => 'count',
    }
);


has not_streaming => ( is => 'ro', isa => 'Bool', default => 0 );


sub reset {
    my ($self) = @_;
    $self->_clear_current_node();
    $self->_clear_finished_nodes();
    $self->_clear_depth_stack();
}


lib/POE/Filter/XML/Handler.pm  view on Meta::CPAN

            $attrib->{'Name'},
            $attrib->{'Value'}
        );
    }

    if($self->depth() == 0)
    {
        #start of a document
        $self->push_depth_stack($node);

        if($self->not_streaming)
        {
            $self->current_node($node);
        }
        else
        {
            $node->_set_stream_start(1);
            $self->add_finished_node($node);
        }
    }
    else
    {
        # Top level fragment
        $self->push_depth_stack($self->current_node);

        if($self->depth() == 2)
        {
            if($self->not_streaming)
            {
                $self->current_node->appendChild($node);
            }
            $self->current_node($node);
        }
        else
        {
            # Some node within a fragment
            $self->current_node->appendChild($node);
            $self->current_node($node);

lib/POE/Filter/XML/Handler.pm  view on Meta::CPAN

    $self->SUPER::start_element($data);
}


sub end_element {
    
    my ($self, $data) = @_;

    if($self->depth() == 1)
    {
        if($self->not_streaming)
        {
            $self->add_finished_node($self->pop_depth_stack());
        }
        else
        {
            my $end = POE::Filter::XML::Node->new($data->{'Name'});
            $end->_set_stream_end(1);
            $self->add_finished_node($end);
        }
    }
    elsif($self->depth() == 2)
    {
        if($self->not_streaming)
        {
            $self->current_node($self->pop_depth_stack());
        }
        else
        {
            $self->add_finished_node($self->current_node);
            $self->_clear_current_node();
            $self->pop_depth_stack();
        }
    }

lib/POE/Filter/XML/Handler.pm  view on Meta::CPAN


POE::Filter::XML::Handler - Default SAX Handler for POE::Filter::XML

=head1 VERSION

version 1.140700

=head1 DESCRIPTION

POE::Filter::XML::Handler is the default SAX handler for POE::Filter::XML. It
extends XML::SAX::Base to provide different semantics for streaming vs.
non-streaming contexts. This handle by default builds POE::Filter::XML::Nodes.

=head1 PUBLIC_ATTRIBUTES

=head2 not_streaming

    is: ro, isa: Bool, default: false

not_streaming determines the behavior for the opening tag parsed. If what is
being parsed is not a stream, the document will be parsed in full then placed
into the finished_nodes attribute. Otherwise, the opening tag will be placed
immediately into the finished_nodes bucket.

=head1 PRIVATE_ATTRIBUTES

=head2 current_node

    is: rw, isa: POE::Filter::XML::Node

lib/POE/Filter/XML/Handler.pm  view on Meta::CPAN


reset will clear the current node, the finished nodes, and the depth stack.

=head1 PROTECTED_METHODS

=head2 override start_element

    (HashRef $data)

start_element is overriden from the XML::SAX::Base class to provide our custom
behavior for dealing with streaming vs. non-streaming data. It builds Nodes
then attaches them to either the root node (non-streaming) or as stand-alone
top level fragments (streaming) sets them to the current node. Children nodes
are appended to their parents before getting set as the current node. Then the
base class method is called via super()

=head2 override end_element

    (HashRef $data)

end_element is overriden from the XML::SAX::Base class to provide our custom
behavior for dealing with streaming vs. non-streaming data. Mostly this method
is in charge of stack management when the depth of the stack reaches certain
points. In streaming documents, this means that top level fragments (not root)
are popped off the stack and added to the finished_nodes collection. Otherwise
a Node is created with stream_end set and added to the finished nodes.

Then the base class method is called via super()

=head2 override characters

    (HashRef $data)

characters merely applies the character data as text to the current node being

lib/POE/Filter/XML/Node.pm  view on Meta::CPAN

package POE::Filter::XML::Node;
{
  $POE::Filter::XML::Node::VERSION = '1.140700';
}

#ABSTRACT: A XML::LibXML::Element subclass that adds streaming semantics

use Moose;
use MooseX::NonMoose;
use MooseX::InsideOut;


extends 'XML::LibXML::Element';

use XML::LibXML(':libxml');

lib/POE/Filter/XML/Node.pm  view on Meta::CPAN

}

1;



=pod

=head1 NAME

POE::Filter::XML::Node - A XML::LibXML::Element subclass that adds streaming semantics

=head1 VERSION

version 1.140700

=head1 SYNOPSIS

    use POE::Filter::XML::Node;

    my $node = POE::Filter::XML::Node->new('iq');

lib/POE/Filter/XML/Node.pm  view on Meta::CPAN


    <iq to='foo@other' from='bar@other' type='get'>
        <query xmlns='jabber:iq:foo'>
            <foo_tag>bar</foo_tag>
        </query>
    </iq>

=head1 DESCRIPTION

POE::Filter::XML::Node is a XML::LibXML::Element subclass that aims to provide
a few extra convenience methods and light integration into a streaming context.

This module can be used to create arbitrarily complex XML data structures that
know how to stringify themselves.

=head1 PUBLIC_ATTRIBUTES

=head2 stream_[start|end]

    is: ro, isa: Bool, default: false

t/02-filter.t  view on Meta::CPAN

    }

    if( $node->nodeName() eq 'testnode' )
    {
        pass('Got testnode 1/3');
        is(ref($node), 'POE::Filter::XML::Node', 'Got testnode 2/3');
        is($node->textContent(), 'THIS IS SOME TEXT', 'Got testnode 3/3');
    }
}

$filter = POE::Filter::XML->new(not_streaming => 1);
$filter->get_one_start([$xml]);
my $node = $filter->get_one()->[0];
is(length($node->toString()), length($xml), 'not_streaming works');

done_testing();



( run in 1.330 second using v1.01-cache-2.11-cpan-140bd7fdf52 )