File Coverage

blib/lib/XML/Xerces/BagOfTricks.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package XML::Xerces::BagOfTricks;
2              
3             =head1 NAME
4              
5             XML::Xerces::BagOfTricks - A library to make XML:Xerces easier and more perl-ish
6              
7             =head1 SYNOPSIS
8              
9             use XML::Xerces::BagOfTricks qw(:all);
10              
11             # get a nice (empty) DOM Document
12             my $DOMDocument = getDocument($namespace,$root_tag);
13              
14             # get a DOM Document from an XML file
15             my $DOMDocument = getDocumentFromXML (file=>$file);
16              
17             # get a DOM Document from an XML file
18             my $DOMDocument = getDocumentFromXML(xml=>$xml);
19              
20             # get a nice Element containing a text node (i.e. bar)
21             my $foo_elem = getTextElement($DOMDocument,'Foo','Bar');
22              
23             # get a nice element with attributes (i.e '')
24             my $foo_elem = getElement($DOMDocument,'Foo','isBar'=>0, 'isFoo'=>1);
25              
26             # get a nice element with attributes that contains a text node
27             my $foo_elem = getElementwithText($DOMDocument,'Foo','Bar',isFoo=>1,isBar=>0);
28             # (i.e. Bar)
29              
30             # if node is not of type Element then append its data to $contents
31             # based on examples in article by P T Darugar.
32             if ( $NodeType[$node->getNodeType()] ne 'Element' ) {
33             $contents .= $node->getData();
34             }
35             # or the easier..
36             my $content = getTextContents($node);
37              
38             # get the nice DOM Document as XML
39             my $xml = getXML($DOMDocument);
40              
41             =head1 DESCRIPTION
42              
43             This module is designed to provide a bag of tricks for users of
44             XML::Xerces DOM API. It provides some useful variables for
45             looking up xerces-c enum values.
46              
47             It also provides functions that make dealing with, creating and
48             printing DOM objects much easier.
49              
50             getTextContents() from 'Effective XML processing with DOM and XPath in Perl'
51             by Parand Tony Darugar, IBM Developerworks Oct 1st 2001
52              
53             =head2 EXPORT
54              
55             ':all' tag exports the following :
56              
57             %NodeType @NodeType $schemaparser $dtdparser $plainparser
58              
59             &getTextContents &getDocument &getDocumentFromXML &getXML
60              
61             &getTextElement &getElement &getElementwithText
62              
63              
64             =head1 FUNCTIONS
65              
66             =cut
67              
68 1     1   21065 use strict;
  1         2  
  1         31  
69              
70 1     1   355 use XML::Xerces;
  0            
  0            
71              
72             require Exporter;
73             use AutoLoader qw(AUTOLOAD);
74              
75             our $VERSION = '0.03';
76             our @ISA = qw(Exporter);
77             our %EXPORT_TAGS = ( 'all' => [ qw(
78             %NodeType @NodeType $schemaparser $dtdparser $plainparser
79             &getTextContents &getDocument &getDocumentFromXML &getXML &getTextElement
80             &getElement &getElementwithText
81             ) ] );
82             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
83              
84             # Xerces implementation and writer
85             my $impl = XML::Xerces::DOMImplementationRegistry::getDOMImplementation('LS');
86             my $writer = $impl->createDOMWriter();
87             if ($writer->canSetFeature('format-pretty-print',1)) {
88             $writer->setFeature('format-pretty-print',1);
89             }
90              
91             # Xerces parsers (one for Schema, DTD and neither)
92             my $validate = $XML::Xerces::AbstractDOMParser::Val_Auto;
93             my $schemaparser = XML::Xerces::XercesDOMParser->new();
94             my $dtdparser = XML::Xerces::XercesDOMParser->new();
95             my $plainparser = XML::Xerces::XercesDOMParser->new();
96             my $error_handler = XML::Xerces::PerlErrorHandler->new();
97             my $c = 0;
98             foreach ( $schemaparser, $dtdparser, $plainparser) {
99             $_->setValidationScheme ($validate);
100             $_->setDoNamespaces (1);
101             $_->setCreateEntityReferenceNodes(1);
102             $_->setErrorHandler($error_handler);
103             }
104             $schemaparser->setDoSchema (1);
105              
106             my $parser = $plainparser;
107              
108             our %NodeType;
109             our @NodeType = qw(ERROR ELEMENT_NODE ATTRIBUTE_NODE TEXT_NODE CDATA_SECTION_NODE ENTITY_REFERENCE_NODE ENTITY_NODE PROCESSING_INSTRUCTION_NODE COMMENT_NODE DOCUMENT_NODE DOCUMENT_TYPE_NODE DOCUMENT_FRAGMENT_NODE NOTATION_NODE );
110             @NodeType{@NodeType} = ( 0 .. 13 );
111              
112             # Preloaded methods go here.
113              
114             # Based on example in 'Effective XML processing with DOM and XPath in Perl'
115             # by Parand Tony Darugar, IBM Developerworks Oct 1st 2001
116              
117             =head2 getTextContents($node)
118              
119             returns the text content of a node (and its subnodes)
120              
121             my $content = getTextContents($node);
122              
123             Function by P T Darugar, published in IBM Developerworks Oct 1st 2001
124              
125             =cut
126             sub getTextContents {
127             my ($node, $strip)= @_;
128             my $contents;
129              
130             if (! $node ) {
131             return;
132             }
133             for my $child ($node->getChildNodes()) {
134             if ( $NodeType[$child->getNodeType()] =~ /(?:TEXT|CDATA_SECTION)_NODE/ ) {
135             $contents .= $child->getData();
136             }
137             }
138              
139             if ($strip) {
140             $contents =~ s/^\s+//;
141             $contents =~ s/\s+$//;
142             }
143              
144             return $contents;
145             }
146              
147             =head2 getTextElement($doc,$name,$value)
148              
149             This function returns a nice XML::Xerces::DOMNode representing an element
150             with an appended Text subnode, based on the arguments provided.
151              
152             In the example below $node would represent 'Bar'
153              
154             my $node = getTextElement($doc,'Foo','Bar');
155              
156             More useful than a pocketful of bent drawing pins! If only the Chilli Peppers
157             made music like they used to 'Zephyr' is no equal of 'Fight Like A Brave' or
158             'Give it away'
159              
160             =cut
161              
162             sub getTextElement {
163             my ($doc, $name, $value) = @_;
164             warn "D'oh! it would be a good idea to provide a value to getTextElement : ", caller() unless $value;
165             my $field = $doc->createElement($name);
166             my $fieldvalue = $doc->createTextNode($value);
167             $field->appendChild($fieldvalue);
168             return $field;
169             }
170              
171             =head2 getElement($doc,$name,%attributes)
172              
173             This function returns a nice XML::Xerces::DOMNode representing an element
174             with an appended Text subnode, based on the arguments provided.
175              
176             In the example below $node would represent ''
177              
178             my $node = getElement($doc,'Foo','isBar'=>0, 'isFoo'=>1);
179              
180             =cut
181              
182              
183             sub getElement {
184             my ($doc, $name, %attributes) = @_;
185             my $node = $doc->createElement($name);
186             foreach my $attr_name (keys %attributes) {
187             if (defined $attributes{$attr_name}) {
188             $node->setAttribute($attr_name,$attributes{$attr_name});
189             }
190             }
191             return $node;
192             }
193              
194              
195             =head2 getElementwithText($DOMDocument,$node_name,$text,$attr_name=>$attr_value);
196              
197             # get a nice element with attributes that contains a text node ( i.e. Bar )
198             my $foo_elem = getElementwithText($DOMDocument,'Foo','Bar',isFoo=>1,isBar=>0);
199              
200             =cut
201              
202             sub getElementwithText {
203             my ($doc, $nodename, $textvalue, %attributes) = @_;
204             my $node = $doc->createElement($nodename);
205             if ($textvalue) {
206             my $text = $doc->createTextNode($textvalue);
207             $node->appendChild($text);
208             }
209             foreach my $attr_name (keys %attributes) {
210             $node->setAttribute($attr_name,$attributes{$attr_name}) if (defined $attributes{$attr_name});
211             }
212             return $node;
213             }
214              
215              
216             =head2 getDocument($namespace,$root_tag)
217              
218             This function will return a nice XML:Xerces::DOMDocument object.
219              
220             It requires a namespace, a root tag, and a list of tags to be added to the document
221              
222             the tags can be scalars :
223              
224             my $doc = getDocument('http://www.some.org/schema/year foo.xsd', 'Foo', 'Bar', 'Baz');
225              
226             or a hashref of attributes, and the tags name :
227              
228             my $doc = getDocument($ns,{name=>'Foo', xmlns=>'http://www.other.org/namespace', version=>1.3}, 'Bar', 'Baz');
229              
230             =cut
231              
232             # maybe we should memoize this later
233              
234             sub getDocument {
235             my ($ns,$root_tag,@tags) = @_;
236             my $docroot = (ref $root_tag) ? $root_tag->{name} : $root_tag;
237             my $doc = eval{$impl->createDocument($ns, $docroot, undef)};
238             XML::Xerces::error($@) if $@;
239             my $root = $doc->getDocumentElement();
240             if (ref $root_tag) {
241             foreach (keys %$root_tag) {
242             next if /name/;
243             $root->setAttribute($_,$root_tag->{$_});
244             }
245             }
246             foreach my $tag ( @tags ) {
247             my $element_tag = (ref $tag) ? $tag->{name} : $tag;
248             my $element = $doc->createElement ($element_tag);
249             if (ref $tag) {
250             foreach (keys %$tag) {
251             next if /name/;
252             $element->setAttribute($_,$tag->{$_});
253             }
254             }
255             $root->appendChild($element);
256             }
257             return $doc;
258              
259             }
260              
261             =head2 getDocumentFromXML
262              
263             Returns an XML::Xerces::DOMDocument object based on the provided input
264              
265             my $DOMDocument = getDocumentFromXML(xml=>$xml);
266              
267             uses the XML::Xerces DOM parser to build a DOM Tree of the given xml
268              
269             my $DOMDocument = getDocumentFromXML (file=>$file);
270              
271             uses the XML::Xerces DOM parser to build a DOM Tree of the given xml
272              
273             =cut
274              
275             sub getDocumentFromXML {
276             my $key = shift;
277             my $value = shift;
278             my $mode;
279              
280             if ( lc($key) eq 'xml') {
281             $mode = 'xml';
282             } elsif (lc $key eq 'file') {
283             $mode = 'file';
284             } else {
285             $mode = ($key =~ /^
286             $value = $key;
287             }
288              
289             my $parser = $plainparser;
290              
291             my $input;
292             if ($mode eq 'xml') {
293             eval { $input = XML::Xerces::MemBufInputSource->new($value); };
294             XML::Xerces::error($@) if ($@);
295             # warn "got buffer : $input \n";
296             } else {
297             $input = $value;
298             }
299              
300             eval { $parser->parse ($input); };
301             XML::Xerces::error($@) if ($@);
302              
303             my $doc;
304             if ($@) {
305             if ($@->isa("XML::Xerces::XMLException")) {
306             warn("XML Exception: type = ".$@->getType.", "
307             ."code = ".$@->getCode.", message = "
308             .$@->getMessage.", src=".$@->getSrcFile." line "
309             .$@->getSrcLine);
310             } else {
311             warn "XML Problem - Got a ".ref($@)." back! we were expecting an XML::Xerces:DOMDocument";
312             XML::Xerces::error($@);
313             }
314             } else {
315             $doc = $parser->getDocument;
316             # warn "XML validated successfully\n";
317             }
318             return $doc;
319             }
320              
321             =head2 getXML($DOMDocument)
322              
323             getXML is exported in the ':all' tag and will return XML in a string
324             generated from the DOM Document passed to it
325              
326             my $xml = getXML($doc);
327              
328             =cut
329              
330             sub getXML {
331             my $doc = shift;
332             my $target = XML::Xerces::MemBufFormatTarget->new();
333             $writer->writeNode($target,$doc);
334             my $xml = $target->getRawBuffer;
335             return $xml;
336             }
337              
338              
339             ################################################################
340              
341             1;
342              
343             __END__