Filename | /usr/lib/x86_64-linux-gnu/perl5/5.20/XML/LibXML.pm |
Statements | Executed 172 statements in 12.3ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 2.52ms | 8.39ms | BEGIN@26 | XML::LibXML::
1 | 1 | 1 | 1.72ms | 1.72ms | bootstrap (xsub) | XML::LibXML::
1 | 1 | 1 | 1.72ms | 5.50ms | BEGIN@27 | XML::LibXML::
1 | 1 | 1 | 1.56ms | 1.69ms | BEGIN@28 | XML::LibXML::
1 | 1 | 1 | 1.56ms | 1.63ms | BEGIN@1536 | XML::LibXML::Element::
4 | 4 | 3 | 50µs | 713µs | import | XML::LibXML::
1 | 1 | 1 | 38µs | 2.25ms | BEGIN@31 | XML::LibXML::
1 | 1 | 1 | 28µs | 28µs | END (xsub) | XML::LibXML::
1 | 1 | 1 | 22µs | 46µs | BEGIN@1271 | XML::LibXML::Node::
1 | 1 | 1 | 13µs | 214µs | BEGIN@237 | XML::LibXML::
1 | 1 | 1 | 13µs | 13µs | LIBXML_RUNTIME_VERSION (xsub) | XML::LibXML::
1 | 1 | 1 | 12µs | 24µs | BEGIN@29 | XML::LibXML::
1 | 1 | 1 | 11µs | 21µs | BEGIN@13 | XML::LibXML::
1 | 1 | 1 | 9µs | 28µs | BEGIN@1539 | XML::LibXML::Element::
1 | 1 | 1 | 8µs | 27µs | BEGIN@1772 | XML::LibXML::Text::
1 | 1 | 1 | 8µs | 35µs | BEGIN@1268 | XML::LibXML::Node::
1 | 1 | 1 | 8µs | 36µs | BEGIN@21 | XML::LibXML::
1 | 1 | 1 | 8µs | 58µs | BEGIN@175 | XML::LibXML::
1 | 1 | 1 | 8µs | 37µs | BEGIN@1537 | XML::LibXML::Element::
1 | 1 | 1 | 7µs | 42µs | BEGIN@169 | XML::LibXML::
1 | 1 | 1 | 7µs | 26µs | BEGIN@1414 | XML::LibXML::Document::
1 | 1 | 1 | 7µs | 7µs | BEGIN@2034 | XML::LibXML::_SAXParser::
1 | 1 | 1 | 7µs | 23µs | BEGIN@1510 | XML::LibXML::DocumentFragment::
1 | 1 | 1 | 7µs | 154µs | BEGIN@1932 | XML::LibXML::NamedNodeMap::
1 | 1 | 1 | 7µs | 123µs | BEGIN@16 | XML::LibXML::
1 | 1 | 1 | 7µs | 33µs | BEGIN@162 | XML::LibXML::
1 | 1 | 1 | 7µs | 22µs | BEGIN@1817 | XML::LibXML::Comment::
1 | 1 | 1 | 7µs | 22µs | BEGIN@1533 | XML::LibXML::Element::
1 | 1 | 1 | 6µs | 21µs | BEGIN@1824 | XML::LibXML::CDATASection::
1 | 1 | 1 | 6µs | 52µs | BEGIN@2178 | XML::LibXML::InputCallback::
1 | 1 | 1 | 6µs | 20µs | BEGIN@1833 | XML::LibXML::Attr::
1 | 1 | 1 | 6µs | 10µs | BEGIN@14 | XML::LibXML::
1 | 1 | 1 | 6µs | 291µs | BEGIN@1535 | XML::LibXML::Element::
1 | 1 | 1 | 6µs | 19µs | BEGIN@1866 | XML::LibXML::PI::
1 | 1 | 1 | 6µs | 43µs | BEGIN@38 | XML::LibXML::
1 | 1 | 1 | 6µs | 39µs | BEGIN@1542 | XML::LibXML::Element::
1 | 1 | 1 | 6µs | 27µs | BEGIN@24 | XML::LibXML::
1 | 1 | 1 | 6µs | 19µs | BEGIN@1855 | XML::LibXML::Dtd::
1 | 1 | 1 | 6µs | 26µs | BEGIN@181 | XML::LibXML::
1 | 1 | 1 | 6µs | 26µs | BEGIN@176 | XML::LibXML::
1 | 1 | 1 | 6µs | 25µs | BEGIN@163 | XML::LibXML::
1 | 1 | 1 | 6µs | 24µs | BEGIN@177 | XML::LibXML::
1 | 1 | 1 | 5µs | 29µs | BEGIN@23 | XML::LibXML::
1 | 1 | 1 | 5µs | 24µs | BEGIN@164 | XML::LibXML::
1 | 1 | 1 | 5µs | 23µs | BEGIN@179 | XML::LibXML::
1 | 1 | 1 | 5µs | 23µs | BEGIN@171 | XML::LibXML::
1 | 1 | 1 | 5µs | 60µs | BEGIN@180 | XML::LibXML::
1 | 1 | 1 | 5µs | 23µs | BEGIN@165 | XML::LibXML::
1 | 1 | 1 | 5µs | 23µs | BEGIN@166 | XML::LibXML::
1 | 1 | 1 | 5µs | 36µs | BEGIN@167 | XML::LibXML::
1 | 1 | 1 | 5µs | 23µs | BEGIN@170 | XML::LibXML::
1 | 1 | 1 | 5µs | 23µs | BEGIN@168 | XML::LibXML::
1 | 1 | 1 | 5µs | 22µs | BEGIN@172 | XML::LibXML::
1 | 1 | 1 | 4µs | 21µs | BEGIN@173 | XML::LibXML::
1 | 1 | 1 | 4µs | 21µs | BEGIN@174 | XML::LibXML::
1 | 1 | 1 | 4µs | 22µs | BEGIN@178 | XML::LibXML::
1 | 1 | 1 | 4µs | 4µs | LIBXML_VERSION (xsub) | XML::LibXML::
7 | 3 | 1 | 4µs | 4µs | CORE:match (opcode) | XML::LibXML::
1 | 1 | 1 | 4µs | 4µs | BEGIN@2180 | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | setNamespace | XML::LibXML::Attr::
0 | 0 | 0 | 0s | 0s | CLONE | XML::LibXML::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::
0 | 0 | 0 | 0s | 0s | actualEncoding | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | insertPI | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | insertProcessingInstruction | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | process_xinclude | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | serialize | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | setDocumentElement | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | toString | XML::LibXML::Document::
0 | 0 | 0 | 0s | 0s | toString | XML::LibXML::DocumentFragment::
0 | 0 | 0 | 0s | 0s | DESTROY | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | __destroy_tiecache | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | _isNotSameNodeLax | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | _isSameNodeLax | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | appendWellBalancedChunk | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getAttribute | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getAttributeHash | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getAttributeNS | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getChildrenByLocalName | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getChildrenByTagName | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getChildrenByTagNameNS | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getElementsByLocalName | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getElementsByTagName | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | getElementsByTagNameNS | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | setAttribute | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | setAttributeNS | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | setNamespace | XML::LibXML::Element::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | _callback_close | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | _callback_match | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | _callback_open | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | _callback_read | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | cleanup_callbacks | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | init_callbacks | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | register_callbacks | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | unregister_callbacks | XML::LibXML::InputCallback::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | getNamedItem | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | getNamedItemNS | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | item | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | length | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | nodes | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | removeNamedItem | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | removeNamedItemNS | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | setNamedItem | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | setNamedItemNS | XML::LibXML::NamedNodeMap::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | getName | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | getNamespaceURI | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | getNamespaces | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | getPrefix | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | isEqualNode | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | isSameNode | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | name | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | nodeName | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | prefix | XML::LibXML::Namespace::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | __ANON__[:1271] | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | __ANON__[:1272] | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | __ANON__[:1273] | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | attributes | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | childNodes | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | exists | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | find | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | findbool | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | findnodes | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | findvalue | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | getChildNodes | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | isSupported | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | nonBlankChildNodes | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | setOwnerDocument | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | toStringC14N | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | toStringC14N_v1_1 | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | toStringEC14N | XML::LibXML::Node::
0 | 0 | 0 | 0s | 0s | setData | XML::LibXML::PI::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::Pattern::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::Pattern::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::RegExp::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::RegExp::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::RelaxNG::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::RelaxNG::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::Schema::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::Schema::
0 | 0 | 0 | 0s | 0s | attributes | XML::LibXML::Text::
0 | 0 | 0 | 0s | 0s | deleteDataString | XML::LibXML::Text::
0 | 0 | 0 | 0s | 0s | replaceDataRegEx | XML::LibXML::Text::
0 | 0 | 0 | 0s | 0s | replaceDataString | XML::LibXML::Text::
0 | 0 | 0 | 0s | 0s | VERSION | XML::LibXML::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::XPathExpression::
0 | 0 | 0 | 0s | 0s | CLONE_SKIP | XML::LibXML::_SAXParser::
0 | 0 | 0 | 0s | 0s | error | XML::LibXML::_SAXParser::
0 | 0 | 0 | 0s | 0s | fatal_error | XML::LibXML::_SAXParser::
0 | 0 | 0 | 0s | 0s | warning | XML::LibXML::_SAXParser::
0 | 0 | 0 | 0s | 0s | __parser_option | XML::LibXML::
0 | 0 | 0 | 0s | 0s | __proxy_registry | XML::LibXML::
0 | 0 | 0 | 0s | 0s | __read | XML::LibXML::
0 | 0 | 0 | 0s | 0s | __write | XML::LibXML::
0 | 0 | 0 | 0s | 0s | _auto_expand | XML::LibXML::
0 | 0 | 0 | 0s | 0s | _cleanup_callbacks | XML::LibXML::
0 | 0 | 0 | 0s | 0s | _clone | XML::LibXML::
0 | 0 | 0 | 0s | 0s | _html_options | XML::LibXML::
0 | 0 | 0 | 0s | 0s | _init_callbacks | XML::LibXML::
0 | 0 | 0 | 0s | 0s | _parser_options | XML::LibXML::
0 | 0 | 0 | 0s | 0s | base_uri | XML::LibXML::
0 | 0 | 0 | 0s | 0s | callbacks | XML::LibXML::
0 | 0 | 0 | 0s | 0s | clean_namespaces | XML::LibXML::
0 | 0 | 0 | 0s | 0s | close_callback | XML::LibXML::
0 | 0 | 0 | 0s | 0s | complete_attributes | XML::LibXML::
0 | 0 | 0 | 0s | 0s | createDocument | XML::LibXML::
0 | 0 | 0 | 0s | 0s | expand_entities | XML::LibXML::
0 | 0 | 0 | 0s | 0s | expand_xinclude | XML::LibXML::
0 | 0 | 0 | 0s | 0s | externalEntityLoader | XML::LibXML::
0 | 0 | 0 | 0s | 0s | finish_push | XML::LibXML::
0 | 0 | 0 | 0s | 0s | gdome_dom | XML::LibXML::
0 | 0 | 0 | 0s | 0s | get_option | XML::LibXML::
0 | 0 | 0 | 0s | 0s | init_push | XML::LibXML::
0 | 0 | 0 | 0s | 0s | input_callbacks | XML::LibXML::
0 | 0 | 0 | 0s | 0s | keep_blanks | XML::LibXML::
0 | 0 | 0 | 0s | 0s | line_numbers | XML::LibXML::
0 | 0 | 0 | 0s | 0s | load_ext_dtd | XML::LibXML::
0 | 0 | 0 | 0s | 0s | load_html | XML::LibXML::
0 | 0 | 0 | 0s | 0s | load_xml | XML::LibXML::
0 | 0 | 0 | 0s | 0s | match_callback | XML::LibXML::
0 | 0 | 0 | 0s | 0s | new | XML::LibXML::
0 | 0 | 0 | 0s | 0s | no_network | XML::LibXML::
0 | 0 | 0 | 0s | 0s | open_callback | XML::LibXML::
0 | 0 | 0 | 0s | 0s | option_exists | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_balanced_chunk | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_chunk | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_fh | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_file | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_html_fh | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_html_file | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_html_string | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_string | XML::LibXML::
0 | 0 | 0 | 0s | 0s | parse_xml_chunk | XML::LibXML::
0 | 0 | 0 | 0s | 0s | pedantic_parser | XML::LibXML::
0 | 0 | 0 | 0s | 0s | processXIncludes | XML::LibXML::
0 | 0 | 0 | 0s | 0s | process_xincludes | XML::LibXML::
0 | 0 | 0 | 0s | 0s | push | XML::LibXML::
0 | 0 | 0 | 0s | 0s | read_callback | XML::LibXML::
0 | 0 | 0 | 0s | 0s | recover | XML::LibXML::
0 | 0 | 0 | 0s | 0s | recover_silently | XML::LibXML::
0 | 0 | 0 | 0s | 0s | set_handler | XML::LibXML::
0 | 0 | 0 | 0s | 0s | set_option | XML::LibXML::
0 | 0 | 0 | 0s | 0s | set_options | XML::LibXML::
0 | 0 | 0 | 0s | 0s | threads_shared_enabled | XML::LibXML::
0 | 0 | 0 | 0s | 0s | validation | XML::LibXML::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # $Id$ | ||||
2 | # | ||||
3 | # | ||||
4 | # This is free software, you may use it and distribute it under the same terms as | ||||
5 | # Perl itself. | ||||
6 | # | ||||
7 | # Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas | ||||
8 | # | ||||
9 | # | ||||
10 | |||||
11 | package XML::LibXML; | ||||
12 | |||||
13 | 2 | 21µs | 2 | 31µs | # spent 21µs (11+10) within XML::LibXML::BEGIN@13 which was called:
# once (11µs+10µs) by MARC::File::XML::BEGIN@9 at line 13 # spent 21µs making 1 call to XML::LibXML::BEGIN@13
# spent 10µs making 1 call to strict::import |
14 | 2 | 35µs | 2 | 14µs | # spent 10µs (6+4) within XML::LibXML::BEGIN@14 which was called:
# once (6µs+4µs) by MARC::File::XML::BEGIN@9 at line 14 # spent 10µs making 1 call to XML::LibXML::BEGIN@14
# spent 4µs making 1 call to warnings::import |
15 | |||||
16 | 1 | 4µs | 1 | 116µs | # spent 123µs (7+116) within XML::LibXML::BEGIN@16 which was called:
# once (7µs+116µs) by MARC::File::XML::BEGIN@9 at line 20 # spent 116µs making 1 call to vars::import |
17 | $skipDTD $skipXMLDeclaration $setTagCompression | ||||
18 | $MatchCB $ReadCB $OpenCB $CloseCB %PARSER_FLAGS | ||||
19 | $XML_LIBXML_PARSE_DEFAULTS | ||||
20 | 1 | 19µs | 1 | 123µs | ); # spent 123µs making 1 call to XML::LibXML::BEGIN@16 |
21 | 2 | 25µs | 2 | 65µs | # spent 36µs (8+28) within XML::LibXML::BEGIN@21 which was called:
# once (8µs+28µs) by MARC::File::XML::BEGIN@9 at line 21 # spent 36µs making 1 call to XML::LibXML::BEGIN@21
# spent 28µs making 1 call to Exporter::import |
22 | |||||
23 | 2 | 22µs | 2 | 53µs | # spent 29µs (5+24) within XML::LibXML::BEGIN@23 which was called:
# once (5µs+24µs) by MARC::File::XML::BEGIN@9 at line 23 # spent 29µs making 1 call to XML::LibXML::BEGIN@23
# spent 24µs making 1 call to constant::import |
24 | 2 | 21µs | 2 | 48µs | # spent 27µs (6+21) within XML::LibXML::BEGIN@24 which was called:
# once (6µs+21µs) by MARC::File::XML::BEGIN@9 at line 24 # spent 27µs making 1 call to XML::LibXML::BEGIN@24
# spent 21µs making 1 call to constant::import |
25 | |||||
26 | 2 | 683µs | 1 | 8.39ms | # spent 8.39ms (2.52+5.87) within XML::LibXML::BEGIN@26 which was called:
# once (2.52ms+5.87ms) by MARC::File::XML::BEGIN@9 at line 26 # spent 8.39ms making 1 call to XML::LibXML::BEGIN@26 |
27 | 2 | 714µs | 1 | 5.50ms | # spent 5.50ms (1.72+3.78) within XML::LibXML::BEGIN@27 which was called:
# once (1.72ms+3.78ms) by MARC::File::XML::BEGIN@9 at line 27 # spent 5.50ms making 1 call to XML::LibXML::BEGIN@27 |
28 | 2 | 742µs | 1 | 1.69ms | # spent 1.69ms (1.56+133µs) within XML::LibXML::BEGIN@28 which was called:
# once (1.56ms+133µs) by MARC::File::XML::BEGIN@9 at line 28 # spent 1.69ms making 1 call to XML::LibXML::BEGIN@28 |
29 | 2 | 50µs | 2 | 37µs | # spent 24µs (12+13) within XML::LibXML::BEGIN@29 which was called:
# once (12µs+13µs) by MARC::File::XML::BEGIN@9 at line 29 # spent 24µs making 1 call to XML::LibXML::BEGIN@29
# spent 13µs making 1 call to Exporter::import |
30 | |||||
31 | # spent 2.25ms (38µs+2.21) within XML::LibXML::BEGIN@31 which was called:
# once (38µs+2.21ms) by MARC::File::XML::BEGIN@9 at line 156 | ||||
32 | 1 | 300ns | $VERSION = "2.0116"; # VERSION TEMPLATE: DO NOT CHANGE | ||
33 | 1 | 100ns | $ABI_VERSION = 2; | ||
34 | 1 | 500ns | require Exporter; | ||
35 | 1 | 600ns | require DynaLoader; | ||
36 | 1 | 9µs | @ISA = qw(DynaLoader Exporter); | ||
37 | |||||
38 | 2 | 252µs | 2 | 80µs | # spent 43µs (6+37) within XML::LibXML::BEGIN@38 which was called:
# once (6µs+37µs) by MARC::File::XML::BEGIN@9 at line 38 # spent 43µs making 1 call to XML::LibXML::BEGIN@38
# spent 37µs making 1 call to vars::import |
39 | |||||
40 | sub VERSION { | ||||
41 | my $class = shift; | ||||
42 | my ($caller) = caller; | ||||
43 | my $req_abi = $ABI_VERSION; | ||||
44 | if (UNIVERSAL::can($caller,'REQUIRE_XML_LIBXML_ABI_VERSION')) { | ||||
45 | $req_abi = $caller->REQUIRE_XML_LIBXML_ABI_VERSION(); | ||||
46 | } elsif ($caller eq 'XML::LibXSLT') { | ||||
47 | # XML::LibXSLT without REQUIRE_XML_LIBXML_ABI_VERSION is an old and incompatible version | ||||
48 | $req_abi = 1; | ||||
49 | } | ||||
50 | unless ($req_abi == $ABI_VERSION) { | ||||
51 | my $ver = @_ ? ' '.$_[0] : ''; | ||||
52 | die ("This version of $caller requires XML::LibXML$ver (ABI $req_abi), which is incompatible with currently installed XML::LibXML $VERSION (ABI $ABI_VERSION). Please upgrade $caller, XML::LibXML, or both!"); | ||||
53 | } | ||||
54 | return $class->UNIVERSAL::VERSION(@_) | ||||
55 | } | ||||
56 | |||||
57 | #-------------------------------------------------------------------------# | ||||
58 | # export information # | ||||
59 | #-------------------------------------------------------------------------# | ||||
60 | 1 | 8µs | %EXPORT_TAGS = ( | ||
61 | all => [qw( | ||||
62 | XML_ELEMENT_NODE | ||||
63 | XML_ATTRIBUTE_NODE | ||||
64 | XML_TEXT_NODE | ||||
65 | XML_CDATA_SECTION_NODE | ||||
66 | XML_ENTITY_REF_NODE | ||||
67 | XML_ENTITY_NODE | ||||
68 | XML_PI_NODE | ||||
69 | XML_COMMENT_NODE | ||||
70 | XML_DOCUMENT_NODE | ||||
71 | XML_DOCUMENT_TYPE_NODE | ||||
72 | XML_DOCUMENT_FRAG_NODE | ||||
73 | XML_NOTATION_NODE | ||||
74 | XML_HTML_DOCUMENT_NODE | ||||
75 | XML_DTD_NODE | ||||
76 | XML_ELEMENT_DECL | ||||
77 | XML_ATTRIBUTE_DECL | ||||
78 | XML_ENTITY_DECL | ||||
79 | XML_NAMESPACE_DECL | ||||
80 | XML_XINCLUDE_END | ||||
81 | XML_XINCLUDE_START | ||||
82 | encodeToUTF8 | ||||
83 | decodeFromUTF8 | ||||
84 | XML_XMLNS_NS | ||||
85 | XML_XML_NS | ||||
86 | )], | ||||
87 | libxml => [qw( | ||||
88 | XML_ELEMENT_NODE | ||||
89 | XML_ATTRIBUTE_NODE | ||||
90 | XML_TEXT_NODE | ||||
91 | XML_CDATA_SECTION_NODE | ||||
92 | XML_ENTITY_REF_NODE | ||||
93 | XML_ENTITY_NODE | ||||
94 | XML_PI_NODE | ||||
95 | XML_COMMENT_NODE | ||||
96 | XML_DOCUMENT_NODE | ||||
97 | XML_DOCUMENT_TYPE_NODE | ||||
98 | XML_DOCUMENT_FRAG_NODE | ||||
99 | XML_NOTATION_NODE | ||||
100 | XML_HTML_DOCUMENT_NODE | ||||
101 | XML_DTD_NODE | ||||
102 | XML_ELEMENT_DECL | ||||
103 | XML_ATTRIBUTE_DECL | ||||
104 | XML_ENTITY_DECL | ||||
105 | XML_NAMESPACE_DECL | ||||
106 | XML_XINCLUDE_END | ||||
107 | XML_XINCLUDE_START | ||||
108 | )], | ||||
109 | encoding => [qw( | ||||
110 | encodeToUTF8 | ||||
111 | decodeFromUTF8 | ||||
112 | )], | ||||
113 | ns => [qw( | ||||
114 | XML_XMLNS_NS | ||||
115 | XML_XML_NS | ||||
116 | )], | ||||
117 | ); | ||||
118 | |||||
119 | @EXPORT_OK = ( | ||||
120 | 1 | 2µs | @{$EXPORT_TAGS{all}}, | ||
121 | ); | ||||
122 | |||||
123 | @EXPORT = ( | ||||
124 | 1 | 1µs | @{$EXPORT_TAGS{all}}, | ||
125 | ); | ||||
126 | |||||
127 | #-------------------------------------------------------------------------# | ||||
128 | # initialization of the global variables # | ||||
129 | #-------------------------------------------------------------------------# | ||||
130 | 1 | 100ns | $skipDTD = 0; | ||
131 | 1 | 100ns | $skipXMLDeclaration = 0; | ||
132 | 1 | 100ns | $setTagCompression = 0; | ||
133 | |||||
134 | 1 | 100ns | $MatchCB = undef; | ||
135 | 1 | 0s | $ReadCB = undef; | ||
136 | 1 | 100ns | $OpenCB = undef; | ||
137 | 1 | 100ns | $CloseCB = undef; | ||
138 | |||||
139 | # if ($threads::threads) { | ||||
140 | # our $__THREADS_TID = 0; | ||||
141 | # eval q{ | ||||
142 | # use threads::shared; | ||||
143 | # our $__PROXY_NODE_REGISTRY_MUTEX :shared = 0; | ||||
144 | # }; | ||||
145 | # die $@ if $@; | ||||
146 | # } | ||||
147 | #-------------------------------------------------------------------------# | ||||
148 | # bootstrapping # | ||||
149 | #-------------------------------------------------------------------------# | ||||
150 | 1 | 7µs | 1 | 2.21ms | bootstrap XML::LibXML $VERSION; # spent 2.21ms making 1 call to DynaLoader::bootstrap |
151 | 1 | 3µs | undef &AUTOLOAD; | ||
152 | |||||
153 | 1 | 900ns | *encodeToUTF8 = \&XML::LibXML::Common::encodeToUTF8; | ||
154 | 1 | 3µs | *decodeFromUTF8 = \&XML::LibXML::Common::decodeFromUTF8; | ||
155 | |||||
156 | 1 | 26µs | 1 | 2.25ms | } # BEGIN # spent 2.25ms making 1 call to XML::LibXML::BEGIN@31 |
157 | |||||
158 | |||||
159 | #-------------------------------------------------------------------------# | ||||
160 | # libxml2 node names (see also XML::LibXML::Common # | ||||
161 | #-------------------------------------------------------------------------# | ||||
162 | 2 | 25µs | 2 | 60µs | # spent 33µs (7+26) within XML::LibXML::BEGIN@162 which was called:
# once (7µs+26µs) by MARC::File::XML::BEGIN@9 at line 162 # spent 33µs making 1 call to XML::LibXML::BEGIN@162
# spent 26µs making 1 call to constant::import |
163 | 2 | 25µs | 2 | 45µs | # spent 25µs (6+20) within XML::LibXML::BEGIN@163 which was called:
# once (6µs+20µs) by MARC::File::XML::BEGIN@9 at line 163 # spent 25µs making 1 call to XML::LibXML::BEGIN@163
# spent 20µs making 1 call to constant::import |
164 | 2 | 20µs | 2 | 43µs | # spent 24µs (5+19) within XML::LibXML::BEGIN@164 which was called:
# once (5µs+19µs) by MARC::File::XML::BEGIN@9 at line 164 # spent 24µs making 1 call to XML::LibXML::BEGIN@164
# spent 19µs making 1 call to constant::import |
165 | 2 | 20µs | 2 | 41µs | # spent 23µs (5+18) within XML::LibXML::BEGIN@165 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 165 # spent 23µs making 1 call to XML::LibXML::BEGIN@165
# spent 18µs making 1 call to constant::import |
166 | 2 | 20µs | 2 | 41µs | # spent 23µs (5+18) within XML::LibXML::BEGIN@166 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 166 # spent 23µs making 1 call to XML::LibXML::BEGIN@166
# spent 18µs making 1 call to constant::import |
167 | 2 | 20µs | 2 | 67µs | # spent 36µs (5+31) within XML::LibXML::BEGIN@167 which was called:
# once (5µs+31µs) by MARC::File::XML::BEGIN@9 at line 167 # spent 36µs making 1 call to XML::LibXML::BEGIN@167
# spent 31µs making 1 call to constant::import |
168 | 2 | 20µs | 2 | 42µs | # spent 23µs (5+18) within XML::LibXML::BEGIN@168 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 168 # spent 23µs making 1 call to XML::LibXML::BEGIN@168
# spent 18µs making 1 call to constant::import |
169 | 2 | 23µs | 2 | 76µs | # spent 42µs (7+34) within XML::LibXML::BEGIN@169 which was called:
# once (7µs+34µs) by MARC::File::XML::BEGIN@9 at line 169 # spent 42µs making 1 call to XML::LibXML::BEGIN@169
# spent 34µs making 1 call to constant::import |
170 | 2 | 20µs | 2 | 41µs | # spent 23µs (5+18) within XML::LibXML::BEGIN@170 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 170 # spent 23µs making 1 call to XML::LibXML::BEGIN@170
# spent 18µs making 1 call to constant::import |
171 | 2 | 19µs | 2 | 40µs | # spent 23µs (5+18) within XML::LibXML::BEGIN@171 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 171 # spent 23µs making 1 call to XML::LibXML::BEGIN@171
# spent 18µs making 1 call to constant::import |
172 | 2 | 19µs | 2 | 40µs | # spent 22µs (5+18) within XML::LibXML::BEGIN@172 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 172 # spent 22µs making 1 call to XML::LibXML::BEGIN@172
# spent 18µs making 1 call to constant::import |
173 | 2 | 19µs | 2 | 38µs | # spent 21µs (4+17) within XML::LibXML::BEGIN@173 which was called:
# once (4µs+17µs) by MARC::File::XML::BEGIN@9 at line 173 # spent 21µs making 1 call to XML::LibXML::BEGIN@173
# spent 17µs making 1 call to constant::import |
174 | 2 | 23µs | 2 | 38µs | # spent 21µs (4+17) within XML::LibXML::BEGIN@174 which was called:
# once (4µs+17µs) by MARC::File::XML::BEGIN@9 at line 174 # spent 21µs making 1 call to XML::LibXML::BEGIN@174
# spent 17µs making 1 call to constant::import |
175 | 2 | 29µs | 2 | 108µs | # spent 58µs (8+50) within XML::LibXML::BEGIN@175 which was called:
# once (8µs+50µs) by MARC::File::XML::BEGIN@9 at line 175 # spent 58µs making 1 call to XML::LibXML::BEGIN@175
# spent 50µs making 1 call to constant::import |
176 | 2 | 26µs | 2 | 47µs | # spent 26µs (6+21) within XML::LibXML::BEGIN@176 which was called:
# once (6µs+21µs) by MARC::File::XML::BEGIN@9 at line 176 # spent 26µs making 1 call to XML::LibXML::BEGIN@176
# spent 21µs making 1 call to constant::import |
177 | 2 | 20µs | 2 | 42µs | # spent 24µs (6+18) within XML::LibXML::BEGIN@177 which was called:
# once (6µs+18µs) by MARC::File::XML::BEGIN@9 at line 177 # spent 24µs making 1 call to XML::LibXML::BEGIN@177
# spent 18µs making 1 call to constant::import |
178 | 2 | 23µs | 2 | 39µs | # spent 22µs (4+17) within XML::LibXML::BEGIN@178 which was called:
# once (4µs+17µs) by MARC::File::XML::BEGIN@9 at line 178 # spent 22µs making 1 call to XML::LibXML::BEGIN@178
# spent 17µs making 1 call to constant::import |
179 | 2 | 19µs | 2 | 40µs | # spent 23µs (5+18) within XML::LibXML::BEGIN@179 which was called:
# once (5µs+18µs) by MARC::File::XML::BEGIN@9 at line 179 # spent 23µs making 1 call to XML::LibXML::BEGIN@179
# spent 18µs making 1 call to constant::import |
180 | 2 | 50µs | 2 | 116µs | # spent 60µs (5+56) within XML::LibXML::BEGIN@180 which was called:
# once (5µs+56µs) by MARC::File::XML::BEGIN@9 at line 180 # spent 60µs making 1 call to XML::LibXML::BEGIN@180
# spent 56µs making 1 call to constant::import |
181 | 2 | 450µs | 2 | 47µs | # spent 26µs (6+21) within XML::LibXML::BEGIN@181 which was called:
# once (6µs+21µs) by MARC::File::XML::BEGIN@9 at line 181 # spent 26µs making 1 call to XML::LibXML::BEGIN@181
# spent 21µs making 1 call to constant::import |
182 | |||||
183 | |||||
184 | # spent 713µs (50+663) within XML::LibXML::import which was called 4 times, avg 178µs/call:
# once (22µs+262µs) by XML::LibXML::Element::BEGIN@1535 at line 1535
# once (13µs+148µs) by Authen::CAS::Client::BEGIN@12 at line 12 of Authen/CAS/Client.pm
# once (9µs+138µs) by XML::LibXML::NamedNodeMap::BEGIN@1932 at line 1932
# once (6µs+114µs) by MARC::File::XML::BEGIN@9 at line 9 of MARC/File/XML.pm | ||||
185 | 4 | 2µs | my $package=shift; | ||
186 | 4 | 17µs | 3 | 800ns | if (grep /^:threads_shared$/, @_) { # spent 800ns making 3 calls to XML::LibXML::CORE:match, avg 267ns/call |
187 | require threads; | ||||
188 | if (!defined($__threads_shared)) { | ||||
189 | if (INIT_THREAD_SUPPORT()) { | ||||
190 | eval q{ | ||||
191 | use threads::shared; | ||||
192 | share($__PROXY_NODE_REGISTRY_MUTEX); | ||||
193 | }; | ||||
194 | if ($@) { # something went wrong | ||||
195 | DISABLE_THREAD_SUPPORT(); # leave the library in a usable state | ||||
196 | die $@; # and die | ||||
197 | } | ||||
198 | $__PROXY_NODE_REGISTRY = XML::LibXML::HashTable->new(); | ||||
199 | $__threads_shared=1; | ||||
200 | } else { | ||||
201 | croak("XML::LibXML or Perl compiled without ithread support!"); | ||||
202 | } | ||||
203 | } elsif (!$__threads_shared) { | ||||
204 | croak("XML::LibXML already loaded without thread support. Too late to enable thread support!"); | ||||
205 | } | ||||
206 | } elsif (defined $XML::LibXML::__loaded) { | ||||
207 | 2 | 1µs | $__threads_shared=0 if not defined $__threads_shared; | ||
208 | } | ||||
209 | 4 | 29µs | 7 | 78µs | __PACKAGE__->export_to_level(1,$package,grep !/^:threads(_shared)?$/,@_); # spent 78µs making 4 calls to Exporter::export_to_level, avg 19µs/call
# spent 300ns making 3 calls to XML::LibXML::CORE:match, avg 100ns/call |
210 | } | ||||
211 | |||||
212 | sub threads_shared_enabled { | ||||
213 | return $__threads_shared ? 1 : 0; | ||||
214 | } | ||||
215 | |||||
216 | # if ($threads::threads) { | ||||
217 | # our $__PROXY_NODE_REGISTRY = XML::LibXML::HashTable->new(); | ||||
218 | # } | ||||
219 | |||||
220 | #-------------------------------------------------------------------------# | ||||
221 | # test exact version (up to patch-level) # | ||||
222 | #-------------------------------------------------------------------------# | ||||
223 | { | ||||
224 | 2 | 25µs | 2 | 16µs | my ($runtime_version) = LIBXML_RUNTIME_VERSION() =~ /^(\d+)/; # spent 13µs making 1 call to XML::LibXML::LIBXML_RUNTIME_VERSION
# spent 3µs making 1 call to XML::LibXML::CORE:match |
225 | 1 | 9µs | 1 | 4µs | if ( $runtime_version < LIBXML_VERSION ) { # spent 4µs making 1 call to XML::LibXML::LIBXML_VERSION |
226 | warn "Warning: XML::LibXML compiled against libxml2 ".LIBXML_VERSION. | ||||
227 | ", but runtime libxml2 is older $runtime_version\n"; | ||||
228 | } | ||||
229 | } | ||||
230 | |||||
231 | |||||
232 | #-------------------------------------------------------------------------# | ||||
233 | # parser flags # | ||||
234 | #-------------------------------------------------------------------------# | ||||
235 | |||||
236 | # Copied directly from http://xmlsoft.org/html/libxml-parser.html#xmlParserOption | ||||
237 | # spent 214µs (13+200) within XML::LibXML::BEGIN@237 which was called:
# once (13µs+200µs) by MARC::File::XML::BEGIN@9 at line 262 | ||||
238 | 1 | 10µs | 1 | 200µs | XML_PARSE_RECOVER => 1, # recover on errors # spent 200µs making 1 call to constant::import |
239 | XML_PARSE_NOENT => 2, # substitute entities | ||||
240 | XML_PARSE_DTDLOAD => 4, # load the external subset | ||||
241 | XML_PARSE_DTDATTR => 8, # default DTD attributes | ||||
242 | XML_PARSE_DTDVALID => 16, # validate with the DTD | ||||
243 | XML_PARSE_NOERROR => 32, # suppress error reports | ||||
244 | XML_PARSE_NOWARNING => 64, # suppress warning reports | ||||
245 | XML_PARSE_PEDANTIC => 128, # pedantic error reporting | ||||
246 | XML_PARSE_NOBLANKS => 256, # remove blank nodes | ||||
247 | XML_PARSE_SAX1 => 512, # use the SAX1 interface internally | ||||
248 | XML_PARSE_XINCLUDE => 1024, # Implement XInclude substitution | ||||
249 | XML_PARSE_NONET => 2048, # Forbid network access | ||||
250 | XML_PARSE_NODICT => 4096, # Do not reuse the context dictionary | ||||
251 | XML_PARSE_NSCLEAN => 8192, # remove redundant namespaces declarations | ||||
252 | XML_PARSE_NOCDATA => 16384, # merge CDATA as text nodes | ||||
253 | XML_PARSE_NOXINCNODE => 32768, # do not generate XINCLUDE START/END nodes | ||||
254 | XML_PARSE_COMPACT => 65536, # compact small text nodes; no modification of the tree allowed afterwards | ||||
255 | # (will possibly crash if you try to modify the tree) | ||||
256 | XML_PARSE_OLD10 => 131072, # parse using XML-1.0 before update 5 | ||||
257 | XML_PARSE_NOBASEFIX => 262144, # do not fixup XINCLUDE xml#base uris | ||||
258 | XML_PARSE_HUGE => 524288, # relax any hardcoded limit from the parser | ||||
259 | XML_PARSE_OLDSAX => 1048576, # parse using SAX2 interface from before 2.7.0 | ||||
260 | HTML_PARSE_RECOVER => (1<<0), # suppress error reports | ||||
261 | HTML_PARSE_NOERROR => (1<<5), # suppress error reports | ||||
262 | 1 | 3.29ms | 1 | 214µs | }; # spent 214µs making 1 call to XML::LibXML::BEGIN@237 |
263 | |||||
264 | 1 | 200ns | $XML_LIBXML_PARSE_DEFAULTS = ( XML_PARSE_NODICT | XML_PARSE_DTDLOAD | XML_PARSE_NOENT ); | ||
265 | |||||
266 | # this hash is made global so that applications can add names for new | ||||
267 | # libxml2 parser flags as temporary workaround | ||||
268 | |||||
269 | 1 | 6µs | %PARSER_FLAGS = ( | ||
270 | recover => XML_PARSE_RECOVER, | ||||
271 | expand_entities => XML_PARSE_NOENT, | ||||
272 | load_ext_dtd => XML_PARSE_DTDLOAD, | ||||
273 | complete_attributes => XML_PARSE_DTDATTR, | ||||
274 | validation => XML_PARSE_DTDVALID, | ||||
275 | suppress_errors => XML_PARSE_NOERROR, | ||||
276 | suppress_warnings => XML_PARSE_NOWARNING, | ||||
277 | pedantic_parser => XML_PARSE_PEDANTIC, | ||||
278 | no_blanks => XML_PARSE_NOBLANKS, | ||||
279 | expand_xinclude => XML_PARSE_XINCLUDE, | ||||
280 | xinclude => XML_PARSE_XINCLUDE, | ||||
281 | no_network => XML_PARSE_NONET, | ||||
282 | clean_namespaces => XML_PARSE_NSCLEAN, | ||||
283 | no_cdata => XML_PARSE_NOCDATA, | ||||
284 | no_xinclude_nodes => XML_PARSE_NOXINCNODE, | ||||
285 | old10 => XML_PARSE_OLD10, | ||||
286 | no_base_fix => XML_PARSE_NOBASEFIX, | ||||
287 | huge => XML_PARSE_HUGE, | ||||
288 | oldsax => XML_PARSE_OLDSAX, | ||||
289 | ); | ||||
290 | |||||
291 | 1 | 2µs | my %OUR_FLAGS = ( | ||
292 | recover => 'XML_LIBXML_RECOVER', | ||||
293 | line_numbers => 'XML_LIBXML_LINENUMBERS', | ||||
294 | URI => 'XML_LIBXML_BASE_URI', | ||||
295 | base_uri => 'XML_LIBXML_BASE_URI', | ||||
296 | gdome => 'XML_LIBXML_GDOME', | ||||
297 | ext_ent_handler => 'ext_ent_handler', | ||||
298 | ); | ||||
299 | |||||
300 | sub _parser_options { | ||||
301 | my ($self, $opts) = @_; | ||||
302 | |||||
303 | # currently dictionaries break XML::LibXML memory management | ||||
304 | |||||
305 | my $flags; | ||||
306 | |||||
307 | if (ref($self)) { | ||||
308 | $flags = ($self->{XML_LIBXML_PARSER_OPTIONS}||0); | ||||
309 | } else { | ||||
310 | $flags = $XML_LIBXML_PARSE_DEFAULTS; # safety precaution | ||||
311 | } | ||||
312 | |||||
313 | my ($key, $value); | ||||
314 | while (($key,$value) = each %$opts) { | ||||
315 | my $f = $PARSER_FLAGS{ $key }; | ||||
316 | if (defined $f) { | ||||
317 | if ($value) { | ||||
318 | $flags |= $f | ||||
319 | } else { | ||||
320 | $flags &= ~$f; | ||||
321 | } | ||||
322 | } elsif ($key eq 'set_parser_flags') { # this can be used to pass flags XML::LibXML does not yet know about | ||||
323 | $flags |= $value; | ||||
324 | } elsif ($key eq 'unset_parser_flags') { | ||||
325 | $flags &= ~$value; | ||||
326 | } | ||||
327 | |||||
328 | } | ||||
329 | return $flags; | ||||
330 | } | ||||
331 | |||||
332 | 1 | 4µs | my %compatibility_flags = ( | ||
333 | XML_LIBXML_VALIDATION => 'validation', | ||||
334 | XML_LIBXML_EXPAND_ENTITIES => 'expand_entities', | ||||
335 | XML_LIBXML_PEDANTIC => 'pedantic_parser', | ||||
336 | XML_LIBXML_NONET => 'no_network', | ||||
337 | XML_LIBXML_EXT_DTD => 'load_ext_dtd', | ||||
338 | XML_LIBXML_COMPLETE_ATTR => 'complete_attributes', | ||||
339 | XML_LIBXML_EXPAND_XINCLUDE => 'expand_xinclude', | ||||
340 | XML_LIBXML_NSCLEAN => 'clean_namespaces', | ||||
341 | XML_LIBXML_KEEP_BLANKS => 'keep_blanks', | ||||
342 | XML_LIBXML_LINENUMBERS => 'line_numbers', | ||||
343 | ); | ||||
344 | |||||
345 | #-------------------------------------------------------------------------# | ||||
346 | # parser constructor # | ||||
347 | #-------------------------------------------------------------------------# | ||||
348 | |||||
349 | |||||
350 | sub new { | ||||
351 | my $class = shift; | ||||
352 | my $self = bless { | ||||
353 | }, $class; | ||||
354 | if (@_) { | ||||
355 | my %opts = (); | ||||
356 | if (ref($_[0]) eq 'HASH') { | ||||
357 | %opts = %{$_[0]}; | ||||
358 | } else { | ||||
359 | # old interface | ||||
360 | my %args = @_; | ||||
361 | %opts=( | ||||
362 | map { | ||||
363 | (($compatibility_flags{ $_ }||$_) => $args{ $_ }) | ||||
364 | } keys %args | ||||
365 | ); | ||||
366 | } | ||||
367 | # parser flags | ||||
368 | $opts{no_blanks} = !$opts{keep_blanks} if exists($opts{keep_blanks}) and !exists($opts{no_blanks}); | ||||
369 | |||||
370 | for (keys %OUR_FLAGS) { | ||||
371 | $self->{$OUR_FLAGS{$_}} = delete $opts{$_}; | ||||
372 | } | ||||
373 | $class->load_catalog(delete($opts{catalog})) if $opts{catalog}; | ||||
374 | |||||
375 | $self->{XML_LIBXML_PARSER_OPTIONS} = XML::LibXML->_parser_options(\%opts); | ||||
376 | |||||
377 | # store remaining unknown options directly in $self | ||||
378 | for (keys %opts) { | ||||
379 | $self->{$_}=$opts{$_} unless exists $PARSER_FLAGS{$_}; | ||||
380 | } | ||||
381 | } else { | ||||
382 | $self->{XML_LIBXML_PARSER_OPTIONS} = $XML_LIBXML_PARSE_DEFAULTS; | ||||
383 | } | ||||
384 | if ( defined $self->{Handler} ) { | ||||
385 | $self->set_handler( $self->{Handler} ); | ||||
386 | } | ||||
387 | |||||
388 | $self->{_State_} = 0; | ||||
389 | return $self; | ||||
390 | } | ||||
391 | |||||
392 | sub _clone { | ||||
393 | my ($self)=@_; | ||||
394 | my $new = ref($self)->new({ | ||||
395 | recover => $self->{XML_LIBXML_RECOVER}, | ||||
396 | line_numbers => $self->{XML_LIBXML_LINENUMBERS}, | ||||
397 | base_uri => $self->{XML_LIBXML_BASE_URI}, | ||||
398 | gdome => $self->{XML_LIBXML_GDOME}, | ||||
399 | set_parser_flags => $self->{XML_LIBXML_PARSER_OPTIONS}, | ||||
400 | }); | ||||
401 | $new->input_callbacks($self->input_callbacks()); | ||||
402 | return $new; | ||||
403 | } | ||||
404 | |||||
405 | #-------------------------------------------------------------------------# | ||||
406 | # Threads support methods # | ||||
407 | #-------------------------------------------------------------------------# | ||||
408 | |||||
409 | # threads doc says CLONE's API may change in future, which would break | ||||
410 | # an XS method prototype | ||||
411 | sub CLONE { | ||||
412 | if ($XML::LibXML::__threads_shared) { | ||||
413 | XML::LibXML::_CLONE( $_[0] ); | ||||
414 | } | ||||
415 | } | ||||
416 | |||||
417 | sub CLONE_SKIP { | ||||
418 | return $XML::LibXML::__threads_shared ? 0 : 1; | ||||
419 | } | ||||
420 | |||||
421 | sub __proxy_registry { | ||||
422 | my ($class)=caller; | ||||
423 | die "This version of $class uses API of XML::LibXML 1.66 which is not compatible with XML::LibXML $VERSION. Please upgrade $class!\n"; | ||||
424 | } | ||||
425 | |||||
426 | #-------------------------------------------------------------------------# | ||||
427 | # DOM Level 2 document constructor # | ||||
428 | #-------------------------------------------------------------------------# | ||||
429 | |||||
430 | sub createDocument { | ||||
431 | my $self = shift; | ||||
432 | if (!@_ or $_[0] =~ m/^\d\.\d$/) { | ||||
433 | # for backward compatibility | ||||
434 | return XML::LibXML::Document->new(@_); | ||||
435 | } | ||||
436 | else { | ||||
437 | # DOM API: createDocument(namespaceURI, qualifiedName, doctype?) | ||||
438 | my $doc = XML::LibXML::Document-> new; | ||||
439 | my $el = $doc->createElementNS(shift, shift); | ||||
440 | $doc->setDocumentElement($el); | ||||
441 | $doc->setExternalSubset(shift) if @_; | ||||
442 | return $doc; | ||||
443 | } | ||||
444 | } | ||||
445 | |||||
446 | #-------------------------------------------------------------------------# | ||||
447 | # callback functions # | ||||
448 | #-------------------------------------------------------------------------# | ||||
449 | |||||
450 | sub externalEntityLoader(&) | ||||
451 | { | ||||
452 | return _externalEntityLoader($_[0]); | ||||
453 | } | ||||
454 | |||||
455 | sub input_callbacks { | ||||
456 | my $self = shift; | ||||
457 | my $icbclass = shift; | ||||
458 | |||||
459 | if ( defined $icbclass ) { | ||||
460 | $self->{XML_LIBXML_CALLBACK_STACK} = $icbclass; | ||||
461 | } | ||||
462 | return $self->{XML_LIBXML_CALLBACK_STACK}; | ||||
463 | } | ||||
464 | |||||
465 | sub match_callback { | ||||
466 | my $self = shift; | ||||
467 | if ( ref $self ) { | ||||
468 | if ( scalar @_ ) { | ||||
469 | $self->{XML_LIBXML_MATCH_CB} = shift; | ||||
470 | $self->{XML_LIBXML_CALLBACK_STACK} = undef; | ||||
471 | } | ||||
472 | return $self->{XML_LIBXML_MATCH_CB}; | ||||
473 | } | ||||
474 | else { | ||||
475 | $MatchCB = shift if scalar @_; | ||||
476 | return $MatchCB; | ||||
477 | } | ||||
478 | } | ||||
479 | |||||
480 | sub read_callback { | ||||
481 | my $self = shift; | ||||
482 | if ( ref $self ) { | ||||
483 | if ( scalar @_ ) { | ||||
484 | $self->{XML_LIBXML_READ_CB} = shift; | ||||
485 | $self->{XML_LIBXML_CALLBACK_STACK} = undef; | ||||
486 | } | ||||
487 | return $self->{XML_LIBXML_READ_CB}; | ||||
488 | } | ||||
489 | else { | ||||
490 | $ReadCB = shift if scalar @_; | ||||
491 | return $ReadCB; | ||||
492 | } | ||||
493 | } | ||||
494 | |||||
495 | sub close_callback { | ||||
496 | my $self = shift; | ||||
497 | if ( ref $self ) { | ||||
498 | if ( scalar @_ ) { | ||||
499 | $self->{XML_LIBXML_CLOSE_CB} = shift; | ||||
500 | $self->{XML_LIBXML_CALLBACK_STACK} = undef; | ||||
501 | } | ||||
502 | return $self->{XML_LIBXML_CLOSE_CB}; | ||||
503 | } | ||||
504 | else { | ||||
505 | $CloseCB = shift if scalar @_; | ||||
506 | return $CloseCB; | ||||
507 | } | ||||
508 | } | ||||
509 | |||||
510 | sub open_callback { | ||||
511 | my $self = shift; | ||||
512 | if ( ref $self ) { | ||||
513 | if ( scalar @_ ) { | ||||
514 | $self->{XML_LIBXML_OPEN_CB} = shift; | ||||
515 | $self->{XML_LIBXML_CALLBACK_STACK} = undef; | ||||
516 | } | ||||
517 | return $self->{XML_LIBXML_OPEN_CB}; | ||||
518 | } | ||||
519 | else { | ||||
520 | $OpenCB = shift if scalar @_; | ||||
521 | return $OpenCB; | ||||
522 | } | ||||
523 | } | ||||
524 | |||||
525 | sub callbacks { | ||||
526 | my $self = shift; | ||||
527 | if ( ref $self ) { | ||||
528 | if (@_) { | ||||
529 | my ($match, $open, $read, $close) = @_; | ||||
530 | @{$self}{qw(XML_LIBXML_MATCH_CB XML_LIBXML_OPEN_CB XML_LIBXML_READ_CB XML_LIBXML_CLOSE_CB)} = ($match, $open, $read, $close); | ||||
531 | $self->{XML_LIBXML_CALLBACK_STACK} = undef; | ||||
532 | } | ||||
533 | else { | ||||
534 | return @{$self}{qw(XML_LIBXML_MATCH_CB XML_LIBXML_OPEN_CB XML_LIBXML_READ_CB XML_LIBXML_CLOSE_CB)}; | ||||
535 | } | ||||
536 | } | ||||
537 | else { | ||||
538 | if (@_) { | ||||
539 | ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ) = @_; | ||||
540 | } | ||||
541 | else { | ||||
542 | return ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ); | ||||
543 | } | ||||
544 | } | ||||
545 | } | ||||
546 | |||||
547 | #-------------------------------------------------------------------------# | ||||
548 | # internal member variable manipulation # | ||||
549 | #-------------------------------------------------------------------------# | ||||
550 | sub __parser_option { | ||||
551 | my ($self, $opt) = @_; | ||||
552 | if (@_>2) { | ||||
553 | if ($_[2]) { | ||||
554 | $self->{XML_LIBXML_PARSER_OPTIONS} |= $opt; | ||||
555 | return 1; | ||||
556 | } else { | ||||
557 | $self->{XML_LIBXML_PARSER_OPTIONS} &= ~$opt; | ||||
558 | return 0; | ||||
559 | } | ||||
560 | } else { | ||||
561 | return ($self->{XML_LIBXML_PARSER_OPTIONS} & $opt) ? 1 : 0; | ||||
562 | } | ||||
563 | } | ||||
564 | |||||
565 | sub option_exists { | ||||
566 | my ($self,$name)=@_; | ||||
567 | return ($PARSER_FLAGS{$name} || $OUR_FLAGS{$name}) ? 1 : 0; | ||||
568 | } | ||||
569 | sub get_option { | ||||
570 | my ($self,$name)=@_; | ||||
571 | my $flag = $OUR_FLAGS{$name}; | ||||
572 | return $self->{$flag} if $flag; | ||||
573 | $flag = $PARSER_FLAGS{$name}; | ||||
574 | return $self->__parser_option($flag) if $flag; | ||||
575 | warn "XML::LibXML::get_option: unknown parser option $name\n"; | ||||
576 | return undef; | ||||
577 | } | ||||
578 | sub set_option { | ||||
579 | my ($self,$name,$value)=@_; | ||||
580 | my $flag = $OUR_FLAGS{$name}; | ||||
581 | return ($self->{$flag}=$value) if $flag; | ||||
582 | $flag = $PARSER_FLAGS{$name}; | ||||
583 | return $self->__parser_option($flag,$value) if $flag; | ||||
584 | warn "XML::LibXML::get_option: unknown parser option $name\n"; | ||||
585 | return undef; | ||||
586 | } | ||||
587 | sub set_options { | ||||
588 | my $self=shift; | ||||
589 | my $opts; | ||||
590 | if (@_==1 and ref($_[0]) eq 'HASH') { | ||||
591 | $opts = $_[0]; | ||||
592 | } elsif (@_ % 2 == 0) { | ||||
593 | $opts={@_}; | ||||
594 | } else { | ||||
595 | croak("Odd number of elements passed to set_options"); | ||||
596 | } | ||||
597 | $self->set_option($_=>$opts->{$_}) foreach keys %$opts; | ||||
598 | return; | ||||
599 | } | ||||
600 | |||||
601 | sub validation { | ||||
602 | my $self = shift; | ||||
603 | return $self->__parser_option(XML_PARSE_DTDVALID,@_); | ||||
604 | } | ||||
605 | |||||
606 | sub recover { | ||||
607 | my $self = shift; | ||||
608 | if (scalar @_) { | ||||
609 | $self->{XML_LIBXML_RECOVER} = $_[0]; | ||||
610 | $self->__parser_option(XML_PARSE_RECOVER,@_); | ||||
611 | } | ||||
612 | return $self->{XML_LIBXML_RECOVER}; | ||||
613 | } | ||||
614 | |||||
615 | sub recover_silently { | ||||
616 | my $self = shift; | ||||
617 | my $arg = shift; | ||||
618 | if ( defined($arg) ) | ||||
619 | { | ||||
620 | $self->recover(($arg == 1) ? 2 : $arg); | ||||
621 | } | ||||
622 | return (($self->recover()||0) == 2) ? 1 : 0; | ||||
623 | } | ||||
624 | |||||
625 | sub expand_entities { | ||||
626 | my $self = shift; | ||||
627 | if (scalar(@_) and $_[0]) { | ||||
628 | return $self->__parser_option(XML_PARSE_NOENT | XML_PARSE_DTDLOAD,1); | ||||
629 | } | ||||
630 | return $self->__parser_option(XML_PARSE_NOENT,@_); | ||||
631 | } | ||||
632 | |||||
633 | sub keep_blanks { | ||||
634 | my $self = shift; | ||||
635 | my @args; # we have to negate the argument and return negated value, since | ||||
636 | # the actual flag is no_blanks | ||||
637 | if (scalar @_) { | ||||
638 | @args=($_[0] ? 0 : 1); | ||||
639 | } | ||||
640 | return $self->__parser_option(XML_PARSE_NOBLANKS,@args) ? 0 : 1; | ||||
641 | } | ||||
642 | |||||
643 | sub pedantic_parser { | ||||
644 | my $self = shift; | ||||
645 | return $self->__parser_option(XML_PARSE_PEDANTIC,@_); | ||||
646 | } | ||||
647 | |||||
648 | sub line_numbers { | ||||
649 | my $self = shift; | ||||
650 | $self->{XML_LIBXML_LINENUMBERS} = shift if scalar @_; | ||||
651 | return $self->{XML_LIBXML_LINENUMBERS}; | ||||
652 | } | ||||
653 | |||||
654 | sub no_network { | ||||
655 | my $self = shift; | ||||
656 | return $self->__parser_option(XML_PARSE_NONET,@_); | ||||
657 | } | ||||
658 | |||||
659 | sub load_ext_dtd { | ||||
660 | my $self = shift; | ||||
661 | return $self->__parser_option(XML_PARSE_DTDLOAD,@_); | ||||
662 | } | ||||
663 | |||||
664 | sub complete_attributes { | ||||
665 | my $self = shift; | ||||
666 | return $self->__parser_option(XML_PARSE_DTDATTR,@_); | ||||
667 | } | ||||
668 | |||||
669 | sub expand_xinclude { | ||||
670 | my $self = shift; | ||||
671 | return $self->__parser_option(XML_PARSE_XINCLUDE,@_); | ||||
672 | } | ||||
673 | |||||
674 | sub base_uri { | ||||
675 | my $self = shift; | ||||
676 | $self->{XML_LIBXML_BASE_URI} = shift if scalar @_; | ||||
677 | return $self->{XML_LIBXML_BASE_URI}; | ||||
678 | } | ||||
679 | |||||
680 | sub gdome_dom { | ||||
681 | my $self = shift; | ||||
682 | $self->{XML_LIBXML_GDOME} = shift if scalar @_; | ||||
683 | return $self->{XML_LIBXML_GDOME}; | ||||
684 | } | ||||
685 | |||||
686 | sub clean_namespaces { | ||||
687 | my $self = shift; | ||||
688 | return $self->__parser_option(XML_PARSE_NSCLEAN,@_); | ||||
689 | } | ||||
690 | |||||
691 | #-------------------------------------------------------------------------# | ||||
692 | # set the optional SAX(2) handler # | ||||
693 | #-------------------------------------------------------------------------# | ||||
694 | sub set_handler { | ||||
695 | my $self = shift; | ||||
696 | if ( defined $_[0] ) { | ||||
697 | $self->{HANDLER} = $_[0]; | ||||
698 | |||||
699 | $self->{SAX_ELSTACK} = []; | ||||
700 | $self->{SAX} = {State => 0}; | ||||
701 | } | ||||
702 | else { | ||||
703 | # undef SAX handling | ||||
704 | $self->{SAX_ELSTACK} = []; | ||||
705 | delete $self->{HANDLER}; | ||||
706 | delete $self->{SAX}; | ||||
707 | } | ||||
708 | } | ||||
709 | |||||
710 | #-------------------------------------------------------------------------# | ||||
711 | # helper functions # | ||||
712 | #-------------------------------------------------------------------------# | ||||
713 | sub _auto_expand { | ||||
714 | my ( $self, $result, $uri ) = @_; | ||||
715 | |||||
716 | $result->setBaseURI( $uri ) if defined $uri; | ||||
717 | |||||
718 | if ( $self->expand_xinclude ) { | ||||
719 | $self->{_State_} = 1; | ||||
720 | eval { $self->processXIncludes($result); }; | ||||
721 | my $err = $@; | ||||
722 | $self->{_State_} = 0; | ||||
723 | if ($err) { | ||||
724 | $self->_cleanup_callbacks(); | ||||
725 | $result = undef; | ||||
726 | croak $err; | ||||
727 | } | ||||
728 | } | ||||
729 | return $result; | ||||
730 | } | ||||
731 | |||||
732 | sub _init_callbacks { | ||||
733 | my $self = shift; | ||||
734 | my $icb = $self->{XML_LIBXML_CALLBACK_STACK}; | ||||
735 | unless ( defined $icb ) { | ||||
736 | $self->{XML_LIBXML_CALLBACK_STACK} = XML::LibXML::InputCallback->new(); | ||||
737 | $icb = $self->{XML_LIBXML_CALLBACK_STACK}; | ||||
738 | } | ||||
739 | |||||
740 | $icb->init_callbacks($self); | ||||
741 | } | ||||
742 | |||||
743 | sub _cleanup_callbacks { | ||||
744 | my $self = shift; | ||||
745 | $self->{XML_LIBXML_CALLBACK_STACK}->cleanup_callbacks(); | ||||
746 | } | ||||
747 | |||||
748 | sub __read { | ||||
749 | read($_[0], $_[1], $_[2]); | ||||
750 | } | ||||
751 | |||||
752 | sub __write { | ||||
753 | if ( ref( $_[0] ) ) { | ||||
754 | $_[0]->write( $_[1], $_[2] ); | ||||
755 | } | ||||
756 | else { | ||||
757 | $_[0]->write( $_[1] ); | ||||
758 | } | ||||
759 | } | ||||
760 | |||||
761 | sub load_xml { | ||||
762 | my $class_or_self = shift; | ||||
763 | my %args = map { ref($_) eq 'HASH' ? (%$_) : $_ } @_; | ||||
764 | |||||
765 | my $URI = delete($args{URI}); | ||||
766 | $URI = "$URI" if defined $URI; # stringify in case it is an URI object | ||||
767 | my $parser; | ||||
768 | if (ref($class_or_self)) { | ||||
769 | $parser = $class_or_self->_clone(); | ||||
770 | $parser->{XML_LIBXML_PARSER_OPTIONS} = $parser->_parser_options(\%args); | ||||
771 | } else { | ||||
772 | $parser = $class_or_self->new(\%args); | ||||
773 | } | ||||
774 | my $dom; | ||||
775 | if ( defined $args{location} ) { | ||||
776 | $dom = $parser->parse_file( "$args{location}" ); | ||||
777 | } | ||||
778 | elsif ( defined $args{string} ) { | ||||
779 | $dom = $parser->parse_string( $args{string}, $URI ); | ||||
780 | } | ||||
781 | elsif ( defined $args{IO} ) { | ||||
782 | $dom = $parser->parse_fh( $args{IO}, $URI ); | ||||
783 | } | ||||
784 | else { | ||||
785 | croak("XML::LibXML->load: specify location, string, or IO"); | ||||
786 | } | ||||
787 | return $dom; | ||||
788 | } | ||||
789 | |||||
790 | sub load_html { | ||||
791 | my ($class_or_self) = shift; | ||||
792 | my %args = map { ref($_) eq 'HASH' ? (%$_) : $_ } @_; | ||||
793 | my $URI = delete($args{URI}); | ||||
794 | $URI = "$URI" if defined $URI; # stringify in case it is an URI object | ||||
795 | my $parser; | ||||
796 | if (ref($class_or_self)) { | ||||
797 | $parser = $class_or_self->_clone(); | ||||
798 | } else { | ||||
799 | $parser = $class_or_self->new(); | ||||
800 | } | ||||
801 | my $dom; | ||||
802 | if ( defined $args{location} ) { | ||||
803 | $dom = $parser->parse_html_file( "$args{location}", \%args ); | ||||
804 | } | ||||
805 | elsif ( defined $args{string} ) { | ||||
806 | $dom = $parser->parse_html_string( $args{string}, \%args ); | ||||
807 | } | ||||
808 | elsif ( defined $args{IO} ) { | ||||
809 | $dom = $parser->parse_html_fh( $args{IO}, \%args ); | ||||
810 | } | ||||
811 | else { | ||||
812 | croak("XML::LibXML->load: specify location, string, or IO"); | ||||
813 | } | ||||
814 | return $dom; | ||||
815 | } | ||||
816 | |||||
817 | #-------------------------------------------------------------------------# | ||||
818 | # parsing functions # | ||||
819 | #-------------------------------------------------------------------------# | ||||
820 | # all parsing functions handle normal as SAX parsing at the same time. | ||||
821 | # note that SAX parsing is handled incomplete! use XML::LibXML::SAX for | ||||
822 | # complete parsing sequences | ||||
823 | #-------------------------------------------------------------------------# | ||||
824 | sub parse_string { | ||||
825 | my $self = shift; | ||||
826 | croak("parse_string is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
827 | croak("parse already in progress") if $self->{_State_}; | ||||
828 | |||||
829 | unless ( defined $_[0] and length $_[0] ) { | ||||
830 | croak("Empty String"); | ||||
831 | } | ||||
832 | |||||
833 | $self->{_State_} = 1; | ||||
834 | my $result; | ||||
835 | |||||
836 | $self->_init_callbacks(); | ||||
837 | |||||
838 | if ( defined $self->{SAX} ) { | ||||
839 | my $string = shift; | ||||
840 | $self->{SAX_ELSTACK} = []; | ||||
841 | eval { $result = $self->_parse_sax_string($string); }; | ||||
842 | my $err = $@; | ||||
843 | $self->{_State_} = 0; | ||||
844 | if ($err) { | ||||
845 | chomp $err unless ref $err; | ||||
846 | $self->_cleanup_callbacks(); | ||||
847 | croak $err; | ||||
848 | } | ||||
849 | } | ||||
850 | else { | ||||
851 | eval { $result = $self->_parse_string( @_ ); }; | ||||
852 | |||||
853 | my $err = $@; | ||||
854 | $self->{_State_} = 0; | ||||
855 | if ($err) { | ||||
856 | chomp $err unless ref $err; | ||||
857 | $self->_cleanup_callbacks(); | ||||
858 | croak $err; | ||||
859 | } | ||||
860 | |||||
861 | $result = $self->_auto_expand( $result, $self->{XML_LIBXML_BASE_URI} ); | ||||
862 | } | ||||
863 | $self->_cleanup_callbacks(); | ||||
864 | |||||
865 | return $result; | ||||
866 | } | ||||
867 | |||||
868 | sub parse_fh { | ||||
869 | my $self = shift; | ||||
870 | croak("parse_fh is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
871 | croak("parse already in progress") if $self->{_State_}; | ||||
872 | $self->{_State_} = 1; | ||||
873 | my $result; | ||||
874 | |||||
875 | $self->_init_callbacks(); | ||||
876 | |||||
877 | if ( defined $self->{SAX} ) { | ||||
878 | $self->{SAX_ELSTACK} = []; | ||||
879 | eval { $self->_parse_sax_fh( @_ ); }; | ||||
880 | my $err = $@; | ||||
881 | $self->{_State_} = 0; | ||||
882 | if ($err) { | ||||
883 | chomp $err unless ref $err; | ||||
884 | $self->_cleanup_callbacks(); | ||||
885 | croak $err; | ||||
886 | } | ||||
887 | } | ||||
888 | else { | ||||
889 | eval { $result = $self->_parse_fh( @_ ); }; | ||||
890 | my $err = $@; | ||||
891 | $self->{_State_} = 0; | ||||
892 | if ($err) { | ||||
893 | chomp $err unless ref $err; | ||||
894 | $self->_cleanup_callbacks(); | ||||
895 | croak $err; | ||||
896 | } | ||||
897 | |||||
898 | $result = $self->_auto_expand( $result, $self->{XML_LIBXML_BASE_URI} ); | ||||
899 | } | ||||
900 | |||||
901 | $self->_cleanup_callbacks(); | ||||
902 | |||||
903 | return $result; | ||||
904 | } | ||||
905 | |||||
906 | sub parse_file { | ||||
907 | my $self = shift; | ||||
908 | croak("parse_file is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
909 | croak("parse already in progress") if $self->{_State_}; | ||||
910 | |||||
911 | $self->{_State_} = 1; | ||||
912 | my $result; | ||||
913 | |||||
914 | $self->_init_callbacks(); | ||||
915 | |||||
916 | if ( defined $self->{SAX} ) { | ||||
917 | $self->{SAX_ELSTACK} = []; | ||||
918 | eval { $self->_parse_sax_file( @_ ); }; | ||||
919 | my $err = $@; | ||||
920 | $self->{_State_} = 0; | ||||
921 | if ($err) { | ||||
922 | chomp $err unless ref $err; | ||||
923 | $self->_cleanup_callbacks(); | ||||
924 | croak $err; | ||||
925 | } | ||||
926 | } | ||||
927 | else { | ||||
928 | eval { $result = $self->_parse_file(@_); }; | ||||
929 | my $err = $@; | ||||
930 | $self->{_State_} = 0; | ||||
931 | if ($err) { | ||||
932 | chomp $err unless ref $err; | ||||
933 | $self->_cleanup_callbacks(); | ||||
934 | croak $err; | ||||
935 | } | ||||
936 | |||||
937 | $result = $self->_auto_expand( $result ); | ||||
938 | } | ||||
939 | $self->_cleanup_callbacks(); | ||||
940 | |||||
941 | return $result; | ||||
942 | } | ||||
943 | |||||
944 | sub parse_xml_chunk { | ||||
945 | my $self = shift; | ||||
946 | # max 2 parameter: | ||||
947 | # 1: the chunk | ||||
948 | # 2: the encoding of the string | ||||
949 | croak("parse_xml_chunk is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
950 | croak("parse already in progress") if $self->{_State_}; my $result; | ||||
951 | |||||
952 | unless ( defined $_[0] and length $_[0] ) { | ||||
953 | croak("Empty String"); | ||||
954 | } | ||||
955 | |||||
956 | $self->{_State_} = 1; | ||||
957 | |||||
958 | $self->_init_callbacks(); | ||||
959 | |||||
960 | if ( defined $self->{SAX} ) { | ||||
961 | eval { | ||||
962 | $self->_parse_sax_xml_chunk( @_ ); | ||||
963 | |||||
964 | # this is required for XML::GenericChunk. | ||||
965 | # in normal case is_filter is not defined, an thus the parsing | ||||
966 | # will be terminated. in case of a SAX filter the parsing is not | ||||
967 | # finished at that state. therefore we must not reset the parsing | ||||
968 | unless ( $self->{IS_FILTER} ) { | ||||
969 | $result = $self->{HANDLER}->end_document(); | ||||
970 | } | ||||
971 | }; | ||||
972 | } | ||||
973 | else { | ||||
974 | eval { $result = $self->_parse_xml_chunk( @_ ); }; | ||||
975 | } | ||||
976 | |||||
977 | $self->_cleanup_callbacks(); | ||||
978 | |||||
979 | my $err = $@; | ||||
980 | $self->{_State_} = 0; | ||||
981 | if ($err) { | ||||
982 | chomp $err unless ref $err; | ||||
983 | croak $err; | ||||
984 | } | ||||
985 | |||||
986 | return $result; | ||||
987 | } | ||||
988 | |||||
989 | sub parse_balanced_chunk { | ||||
990 | my $self = shift; | ||||
991 | $self->_init_callbacks(); | ||||
992 | my $rv; | ||||
993 | eval { | ||||
994 | $rv = $self->parse_xml_chunk( @_ ); | ||||
995 | }; | ||||
996 | my $err = $@; | ||||
997 | $self->_cleanup_callbacks(); | ||||
998 | if ( $err ) { | ||||
999 | chomp $err unless ref $err; | ||||
1000 | croak $err; | ||||
1001 | } | ||||
1002 | return $rv | ||||
1003 | } | ||||
1004 | |||||
1005 | # java style | ||||
1006 | sub processXIncludes { | ||||
1007 | my $self = shift; | ||||
1008 | my $doc = shift; | ||||
1009 | my $opts = shift; | ||||
1010 | my $options = $self->_parser_options($opts); | ||||
1011 | if ( $self->{_State_} != 1 ) { | ||||
1012 | $self->_init_callbacks(); | ||||
1013 | } | ||||
1014 | my $rv; | ||||
1015 | eval { | ||||
1016 | $rv = $self->_processXIncludes($doc || " ", $options); | ||||
1017 | }; | ||||
1018 | my $err = $@; | ||||
1019 | if ( $self->{_State_} != 1 ) { | ||||
1020 | $self->_cleanup_callbacks(); | ||||
1021 | } | ||||
1022 | |||||
1023 | if ( $err ) { | ||||
1024 | chomp $err unless ref $err; | ||||
1025 | croak $err; | ||||
1026 | } | ||||
1027 | return $rv; | ||||
1028 | } | ||||
1029 | |||||
1030 | # perl style | ||||
1031 | sub process_xincludes { | ||||
1032 | my $self = shift; | ||||
1033 | my $doc = shift; | ||||
1034 | my $opts = shift; | ||||
1035 | my $options = $self->_parser_options($opts); | ||||
1036 | |||||
1037 | my $rv; | ||||
1038 | $self->_init_callbacks(); | ||||
1039 | eval { | ||||
1040 | $rv = $self->_processXIncludes($doc || " ", $options); | ||||
1041 | }; | ||||
1042 | my $err = $@; | ||||
1043 | $self->_cleanup_callbacks(); | ||||
1044 | if ( $err ) { | ||||
1045 | chomp $err unless ref $err; | ||||
1046 | croak $@; | ||||
1047 | } | ||||
1048 | return $rv; | ||||
1049 | } | ||||
1050 | |||||
1051 | #-------------------------------------------------------------------------# | ||||
1052 | # HTML parsing functions # | ||||
1053 | #-------------------------------------------------------------------------# | ||||
1054 | |||||
1055 | sub _html_options { | ||||
1056 | my ($self,$opts)=@_; | ||||
1057 | $opts = {} unless ref $opts; | ||||
1058 | # return (undef,undef) unless ref $opts; | ||||
1059 | my $flags = 0; | ||||
1060 | { | ||||
1061 | my $recover = exists $opts->{recover} ? $opts->{recover} : $self->recover; | ||||
1062 | |||||
1063 | if ($recover) | ||||
1064 | { | ||||
1065 | $flags |= HTML_PARSE_RECOVER; | ||||
1066 | if ($recover == 2) | ||||
1067 | { | ||||
1068 | $flags |= HTML_PARSE_NOERROR; | ||||
1069 | } | ||||
1070 | } | ||||
1071 | } | ||||
1072 | |||||
1073 | $flags |= 4 if $opts->{no_defdtd}; # default is ON: injects DTD as needed | ||||
1074 | $flags |= 32 if exists $opts->{suppress_errors} ? $opts->{suppress_errors} : $self->get_option('suppress_errors'); | ||||
1075 | # This is to fix https://rt.cpan.org/Ticket/Display.html?id=58024 : | ||||
1076 | # <quote> | ||||
1077 | # In XML::LibXML, warnings are not suppressed when specifying the recover | ||||
1078 | # or recover_silently flags as per the following excerpt from the manpage: | ||||
1079 | # </quote> | ||||
1080 | if ($self->recover_silently) | ||||
1081 | { | ||||
1082 | $flags |= 32; | ||||
1083 | } | ||||
1084 | $flags |= 64 if $opts->{suppress_warnings}; | ||||
1085 | $flags |= 128 if exists $opts->{pedantic_parser} ? $opts->{pedantic_parser} : $self->pedantic_parser; | ||||
1086 | $flags |= 256 if exists $opts->{no_blanks} ? $opts->{no_blanks} : !$self->keep_blanks; | ||||
1087 | $flags |= 2048 if exists $opts->{no_network} ? $opts->{no_network} : !$self->no_network; | ||||
1088 | $flags |= 16384 if $opts->{no_cdata}; | ||||
1089 | $flags |= 65536 if $opts->{compact}; # compact small text nodes; no modification | ||||
1090 | # of the tree allowed afterwards | ||||
1091 | # (WILL possibly CRASH IF YOU try to MODIFY THE TREE) | ||||
1092 | $flags |= 524288 if $opts->{huge}; # relax any hardcoded limit from the parser | ||||
1093 | $flags |= 1048576 if $opts->{oldsax}; # parse using SAX2 interface from before 2.7.0 | ||||
1094 | |||||
1095 | return ($opts->{URI},$opts->{encoding},$flags); | ||||
1096 | } | ||||
1097 | |||||
1098 | sub parse_html_string { | ||||
1099 | my ($self,$str,$opts) = @_; | ||||
1100 | croak("parse_html_string is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
1101 | croak("parse already in progress") if $self->{_State_}; | ||||
1102 | |||||
1103 | unless ( defined $str and length $str ) { | ||||
1104 | croak("Empty String"); | ||||
1105 | } | ||||
1106 | $self->{_State_} = 1; | ||||
1107 | my $result; | ||||
1108 | |||||
1109 | $self->_init_callbacks(); | ||||
1110 | eval { | ||||
1111 | $result = $self->_parse_html_string( $str, | ||||
1112 | $self->_html_options($opts) | ||||
1113 | ); | ||||
1114 | }; | ||||
1115 | my $err = $@; | ||||
1116 | $self->{_State_} = 0; | ||||
1117 | if ($err) { | ||||
1118 | chomp $err unless ref $err; | ||||
1119 | $self->_cleanup_callbacks(); | ||||
1120 | croak $err; | ||||
1121 | } | ||||
1122 | |||||
1123 | $self->_cleanup_callbacks(); | ||||
1124 | |||||
1125 | return $result; | ||||
1126 | } | ||||
1127 | |||||
1128 | sub parse_html_file { | ||||
1129 | my ($self,$file,$opts) = @_; | ||||
1130 | croak("parse_html_file is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
1131 | croak("parse already in progress") if $self->{_State_}; | ||||
1132 | $self->{_State_} = 1; | ||||
1133 | my $result; | ||||
1134 | |||||
1135 | $self->_init_callbacks(); | ||||
1136 | eval { $result = $self->_parse_html_file($file, | ||||
1137 | $self->_html_options($opts) | ||||
1138 | ); }; | ||||
1139 | my $err = $@; | ||||
1140 | $self->{_State_} = 0; | ||||
1141 | if ($err) { | ||||
1142 | chomp $err unless ref $err; | ||||
1143 | $self->_cleanup_callbacks(); | ||||
1144 | croak $err; | ||||
1145 | } | ||||
1146 | |||||
1147 | $self->_cleanup_callbacks(); | ||||
1148 | |||||
1149 | return $result; | ||||
1150 | } | ||||
1151 | |||||
1152 | sub parse_html_fh { | ||||
1153 | my ($self,$fh,$opts) = @_; | ||||
1154 | croak("parse_html_fh is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; | ||||
1155 | croak("parse already in progress") if $self->{_State_}; | ||||
1156 | $self->{_State_} = 1; | ||||
1157 | |||||
1158 | my $result; | ||||
1159 | $self->_init_callbacks(); | ||||
1160 | eval { $result = $self->_parse_html_fh( $fh, | ||||
1161 | $self->_html_options($opts) | ||||
1162 | ); }; | ||||
1163 | my $err = $@; | ||||
1164 | $self->{_State_} = 0; | ||||
1165 | if ($err) { | ||||
1166 | chomp $err unless ref $err; | ||||
1167 | $self->_cleanup_callbacks(); | ||||
1168 | croak $err; | ||||
1169 | } | ||||
1170 | $self->_cleanup_callbacks(); | ||||
1171 | |||||
1172 | return $result; | ||||
1173 | } | ||||
1174 | |||||
1175 | #-------------------------------------------------------------------------# | ||||
1176 | # push parser interface # | ||||
1177 | #-------------------------------------------------------------------------# | ||||
1178 | sub init_push { | ||||
1179 | my $self = shift; | ||||
1180 | |||||
1181 | if ( defined $self->{CONTEXT} ) { | ||||
1182 | delete $self->{CONTEXT}; | ||||
1183 | } | ||||
1184 | |||||
1185 | if ( defined $self->{SAX} ) { | ||||
1186 | $self->{CONTEXT} = $self->_start_push(1); | ||||
1187 | } | ||||
1188 | else { | ||||
1189 | $self->{CONTEXT} = $self->_start_push(0); | ||||
1190 | } | ||||
1191 | } | ||||
1192 | |||||
1193 | sub push { | ||||
1194 | my $self = shift; | ||||
1195 | |||||
1196 | $self->_init_callbacks(); | ||||
1197 | |||||
1198 | if ( not defined $self->{CONTEXT} ) { | ||||
1199 | $self->init_push(); | ||||
1200 | } | ||||
1201 | |||||
1202 | eval { | ||||
1203 | foreach ( @_ ) { | ||||
1204 | $self->_push( $self->{CONTEXT}, $_ ); | ||||
1205 | } | ||||
1206 | }; | ||||
1207 | my $err = $@; | ||||
1208 | $self->_cleanup_callbacks(); | ||||
1209 | if ( $err ) { | ||||
1210 | chomp $err unless ref $err; | ||||
1211 | croak $err; | ||||
1212 | } | ||||
1213 | } | ||||
1214 | |||||
1215 | # this function should be promoted! | ||||
1216 | # the reason is because libxml2 uses xmlParseChunk() for this purpose! | ||||
1217 | sub parse_chunk { | ||||
1218 | my $self = shift; | ||||
1219 | my $chunk = shift; | ||||
1220 | my $terminate = shift; | ||||
1221 | |||||
1222 | if ( not defined $self->{CONTEXT} ) { | ||||
1223 | $self->init_push(); | ||||
1224 | } | ||||
1225 | |||||
1226 | if ( defined $chunk and length $chunk ) { | ||||
1227 | $self->_push( $self->{CONTEXT}, $chunk ); | ||||
1228 | } | ||||
1229 | |||||
1230 | if ( $terminate ) { | ||||
1231 | return $self->finish_push(); | ||||
1232 | } | ||||
1233 | } | ||||
1234 | |||||
1235 | |||||
1236 | sub finish_push { | ||||
1237 | my $self = shift; | ||||
1238 | my $restore = shift || 0; | ||||
1239 | return undef unless defined $self->{CONTEXT}; | ||||
1240 | |||||
1241 | my $retval; | ||||
1242 | |||||
1243 | if ( defined $self->{SAX} ) { | ||||
1244 | eval { | ||||
1245 | $self->_end_sax_push( $self->{CONTEXT} ); | ||||
1246 | $retval = $self->{HANDLER}->end_document( {} ); | ||||
1247 | }; | ||||
1248 | } | ||||
1249 | else { | ||||
1250 | eval { $retval = $self->_end_push( $self->{CONTEXT}, $restore ); }; | ||||
1251 | } | ||||
1252 | my $err = $@; | ||||
1253 | delete $self->{CONTEXT}; | ||||
1254 | if ( $err ) { | ||||
1255 | chomp $err unless ref $err; | ||||
1256 | croak( $err ); | ||||
1257 | } | ||||
1258 | return $retval; | ||||
1259 | } | ||||
1260 | |||||
1261 | 1; | ||||
1262 | |||||
1263 | #-------------------------------------------------------------------------# | ||||
1264 | # XML::LibXML::Node Interface # | ||||
1265 | #-------------------------------------------------------------------------# | ||||
1266 | package XML::LibXML::Node; | ||||
1267 | |||||
1268 | 2 | 100µs | 2 | 62µs | # spent 35µs (8+27) within XML::LibXML::Node::BEGIN@1268 which was called:
# once (8µs+27µs) by MARC::File::XML::BEGIN@9 at line 1268 # spent 35µs making 1 call to XML::LibXML::Node::BEGIN@1268
# spent 27µs making 1 call to Exporter::import |
1269 | |||||
1270 | use overload | ||||
1271 | # spent 46µs (22+24) within XML::LibXML::Node::BEGIN@1271 which was called:
# once (22µs+24µs) by MARC::File::XML::BEGIN@9 at line 1275 | ||||
1272 | 'bool' => sub { 1 }, | ||||
1273 | '0+' => sub { Scalar::Util::refaddr($_[0]) }, | ||||
1274 | 1 | 6µs | 1 | 24µs | fallback => 1, # spent 24µs making 1 call to overload::import |
1275 | 1 | 537µs | 1 | 46µs | ; # spent 46µs making 1 call to XML::LibXML::Node::BEGIN@1271 |
1276 | |||||
1277 | |||||
1278 | sub CLONE_SKIP { | ||||
1279 | return $XML::LibXML::__threads_shared ? 0 : 1; | ||||
1280 | } | ||||
1281 | |||||
1282 | sub isSupported { | ||||
1283 | my $self = shift; | ||||
1284 | my $feature = shift; | ||||
1285 | return $self->can($feature) ? 1 : 0; | ||||
1286 | } | ||||
1287 | |||||
1288 | sub getChildNodes { my $self = shift; return $self->childNodes(); } | ||||
1289 | |||||
1290 | sub childNodes { | ||||
1291 | my $self = shift; | ||||
1292 | my @children = $self->_childNodes(0); | ||||
1293 | return wantarray ? @children : XML::LibXML::NodeList->new_from_ref(\@children , 1); | ||||
1294 | } | ||||
1295 | |||||
1296 | sub nonBlankChildNodes { | ||||
1297 | my $self = shift; | ||||
1298 | my @children = $self->_childNodes(1); | ||||
1299 | return wantarray ? @children : XML::LibXML::NodeList->new_from_ref(\@children , 1); | ||||
1300 | } | ||||
1301 | |||||
1302 | sub attributes { | ||||
1303 | my $self = shift; | ||||
1304 | my @attr = $self->_attributes(); | ||||
1305 | return wantarray ? @attr : XML::LibXML::NamedNodeMap->new( @attr ); | ||||
1306 | } | ||||
1307 | |||||
1308 | |||||
1309 | sub findnodes { | ||||
1310 | my ($node, $xpath) = @_; | ||||
1311 | my @nodes = $node->_findnodes($xpath); | ||||
1312 | if (wantarray) { | ||||
1313 | return @nodes; | ||||
1314 | } | ||||
1315 | else { | ||||
1316 | return XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1317 | } | ||||
1318 | } | ||||
1319 | |||||
1320 | sub exists { | ||||
1321 | my ($node, $xpath) = @_; | ||||
1322 | my (undef, $value) = $node->_find($xpath,1); | ||||
1323 | return $value; | ||||
1324 | } | ||||
1325 | |||||
1326 | sub findvalue { | ||||
1327 | my ($node, $xpath) = @_; | ||||
1328 | my $res; | ||||
1329 | $res = $node->find($xpath); | ||||
1330 | return $res->to_literal->value; | ||||
1331 | } | ||||
1332 | |||||
1333 | sub findbool { | ||||
1334 | my ($node, $xpath) = @_; | ||||
1335 | my ($type, @params) = $node->_find($xpath,1); | ||||
1336 | if ($type) { | ||||
1337 | return $type->new(@params); | ||||
1338 | } | ||||
1339 | return undef; | ||||
1340 | } | ||||
1341 | |||||
1342 | sub find { | ||||
1343 | my ($node, $xpath) = @_; | ||||
1344 | my ($type, @params) = $node->_find($xpath,0); | ||||
1345 | if ($type) { | ||||
1346 | return $type->new(@params); | ||||
1347 | } | ||||
1348 | return undef; | ||||
1349 | } | ||||
1350 | |||||
1351 | sub setOwnerDocument { | ||||
1352 | my ( $self, $doc ) = @_; | ||||
1353 | $doc->adoptNode( $self ); | ||||
1354 | } | ||||
1355 | |||||
1356 | sub toStringC14N { | ||||
1357 | my ($self, $comments, $xpath, $xpc) = @_; | ||||
1358 | return $self->_toStringC14N( $comments || 0, | ||||
1359 | (defined $xpath ? $xpath : undef), | ||||
1360 | 0, | ||||
1361 | undef, | ||||
1362 | (defined $xpc ? $xpc : undef) | ||||
1363 | ); | ||||
1364 | } | ||||
1365 | |||||
1366 | { | ||||
1367 | 2 | 400ns | my $C14N_version_1_dot_1_val = 2; | ||
1368 | |||||
1369 | sub toStringC14N_v1_1 { | ||||
1370 | my ($self, $comments, $xpath, $xpc) = @_; | ||||
1371 | |||||
1372 | return $self->_toStringC14N( | ||||
1373 | $comments || 0, | ||||
1374 | (defined $xpath ? $xpath : undef), | ||||
1375 | $C14N_version_1_dot_1_val, | ||||
1376 | undef, | ||||
1377 | (defined $xpc ? $xpc : undef) | ||||
1378 | ); | ||||
1379 | } | ||||
1380 | |||||
1381 | } | ||||
1382 | |||||
1383 | sub toStringEC14N { | ||||
1384 | my ($self, $comments, $xpath, $xpc, $inc_prefix_list) = @_; | ||||
1385 | unless (UNIVERSAL::isa($xpc,'XML::LibXML::XPathContext')) { | ||||
1386 | if ($inc_prefix_list) { | ||||
1387 | croak("toStringEC14N: 3rd argument is not an XML::LibXML::XPathContext"); | ||||
1388 | } else { | ||||
1389 | $inc_prefix_list=$xpc; | ||||
1390 | $xpc=undef; | ||||
1391 | } | ||||
1392 | } | ||||
1393 | if (defined($inc_prefix_list) and !UNIVERSAL::isa($inc_prefix_list,'ARRAY')) { | ||||
1394 | croak("toStringEC14N: inclusive_prefix_list must be undefined or ARRAY"); | ||||
1395 | } | ||||
1396 | return $self->_toStringC14N( $comments || 0, | ||||
1397 | (defined $xpath ? $xpath : undef), | ||||
1398 | 1, | ||||
1399 | (defined $inc_prefix_list ? $inc_prefix_list : undef), | ||||
1400 | (defined $xpc ? $xpc : undef) | ||||
1401 | ); | ||||
1402 | } | ||||
1403 | |||||
1404 | 1 | 1µs | *serialize_c14n = \&toStringC14N; | ||
1405 | 1 | 300ns | *serialize_exc_c14n = \&toStringEC14N; | ||
1406 | |||||
1407 | 1; | ||||
1408 | |||||
1409 | #-------------------------------------------------------------------------# | ||||
1410 | # XML::LibXML::Document Interface # | ||||
1411 | #-------------------------------------------------------------------------# | ||||
1412 | package XML::LibXML::Document; | ||||
1413 | |||||
1414 | 2 | 332µs | 2 | 46µs | # spent 26µs (7+19) within XML::LibXML::Document::BEGIN@1414 which was called:
# once (7µs+19µs) by MARC::File::XML::BEGIN@9 at line 1414 # spent 26µs making 1 call to XML::LibXML::Document::BEGIN@1414
# spent 19µs making 1 call to vars::import |
1415 | 1 | 6µs | @ISA = ('XML::LibXML::Node'); | ||
1416 | |||||
1417 | sub actualEncoding { | ||||
1418 | my $doc = shift; | ||||
1419 | my $enc = $doc->encoding; | ||||
1420 | return (defined $enc and length $enc) ? $enc : 'UTF-8'; | ||||
1421 | } | ||||
1422 | |||||
1423 | sub setDocumentElement { | ||||
1424 | my $doc = shift; | ||||
1425 | my $element = shift; | ||||
1426 | |||||
1427 | my $oldelem = $doc->documentElement; | ||||
1428 | if ( defined $oldelem ) { | ||||
1429 | $doc->removeChild($oldelem); | ||||
1430 | } | ||||
1431 | |||||
1432 | $doc->_setDocumentElement($element); | ||||
1433 | } | ||||
1434 | |||||
1435 | sub toString { | ||||
1436 | my $self = shift; | ||||
1437 | my $flag = shift; | ||||
1438 | |||||
1439 | my $retval = ""; | ||||
1440 | |||||
1441 | if ( defined $XML::LibXML::skipXMLDeclaration | ||||
1442 | and $XML::LibXML::skipXMLDeclaration == 1 ) { | ||||
1443 | foreach ( $self->childNodes ){ | ||||
1444 | next if $_->nodeType == XML::LibXML::XML_DTD_NODE() | ||||
1445 | and $XML::LibXML::skipDTD; | ||||
1446 | $retval .= $_->toString; | ||||
1447 | } | ||||
1448 | } | ||||
1449 | else { | ||||
1450 | $flag ||= 0 unless defined $flag; | ||||
1451 | $retval = $self->_toString($flag); | ||||
1452 | } | ||||
1453 | |||||
1454 | return $retval; | ||||
1455 | } | ||||
1456 | |||||
1457 | sub serialize { | ||||
1458 | my $self = shift; | ||||
1459 | return $self->toString( @_ ); | ||||
1460 | } | ||||
1461 | |||||
1462 | #-------------------------------------------------------------------------# | ||||
1463 | # bad style xinclude processing # | ||||
1464 | #-------------------------------------------------------------------------# | ||||
1465 | sub process_xinclude { | ||||
1466 | my $self = shift; | ||||
1467 | my $opts = shift; | ||||
1468 | XML::LibXML->new->processXIncludes( $self, $opts ); | ||||
1469 | } | ||||
1470 | |||||
1471 | sub insertProcessingInstruction { | ||||
1472 | my $self = shift; | ||||
1473 | my $target = shift; | ||||
1474 | my $data = shift; | ||||
1475 | |||||
1476 | my $pi = $self->createPI( $target, $data ); | ||||
1477 | my $root = $self->documentElement; | ||||
1478 | |||||
1479 | if ( defined $root ) { | ||||
1480 | # this is actually not correct, but i guess it's what the user | ||||
1481 | # intends | ||||
1482 | $self->insertBefore( $pi, $root ); | ||||
1483 | } | ||||
1484 | else { | ||||
1485 | # if no documentElement was found we just append the PI | ||||
1486 | $self->appendChild( $pi ); | ||||
1487 | } | ||||
1488 | } | ||||
1489 | |||||
1490 | sub insertPI { | ||||
1491 | my $self = shift; | ||||
1492 | $self->insertProcessingInstruction( @_ ); | ||||
1493 | } | ||||
1494 | |||||
1495 | #-------------------------------------------------------------------------# | ||||
1496 | # DOM L3 Document functions. | ||||
1497 | # added after robins implicit feature request | ||||
1498 | #-------------------------------------------------------------------------# | ||||
1499 | 1 | 400ns | *getElementsByTagName = \&XML::LibXML::Element::getElementsByTagName; | ||
1500 | 1 | 100ns | *getElementsByTagNameNS = \&XML::LibXML::Element::getElementsByTagNameNS; | ||
1501 | 1 | 100ns | *getElementsByLocalName = \&XML::LibXML::Element::getElementsByLocalName; | ||
1502 | |||||
1503 | 1; | ||||
1504 | |||||
1505 | #-------------------------------------------------------------------------# | ||||
1506 | # XML::LibXML::DocumentFragment Interface # | ||||
1507 | #-------------------------------------------------------------------------# | ||||
1508 | package XML::LibXML::DocumentFragment; | ||||
1509 | |||||
1510 | 2 | 92µs | 2 | 39µs | # spent 23µs (7+16) within XML::LibXML::DocumentFragment::BEGIN@1510 which was called:
# once (7µs+16µs) by MARC::File::XML::BEGIN@9 at line 1510 # spent 23µs making 1 call to XML::LibXML::DocumentFragment::BEGIN@1510
# spent 16µs making 1 call to vars::import |
1511 | 1 | 2µs | @ISA = ('XML::LibXML::Node'); | ||
1512 | |||||
1513 | sub toString { | ||||
1514 | my $self = shift; | ||||
1515 | my $retval = ""; | ||||
1516 | if ( $self->hasChildNodes() ) { | ||||
1517 | foreach my $n ( $self->childNodes() ) { | ||||
1518 | $retval .= $n->toString(@_); | ||||
1519 | } | ||||
1520 | } | ||||
1521 | return $retval; | ||||
1522 | } | ||||
1523 | |||||
1524 | 1 | 400ns | *serialize = \&toString; | ||
1525 | |||||
1526 | 1; | ||||
1527 | |||||
1528 | #-------------------------------------------------------------------------# | ||||
1529 | # XML::LibXML::Element Interface # | ||||
1530 | #-------------------------------------------------------------------------# | ||||
1531 | package XML::LibXML::Element; | ||||
1532 | |||||
1533 | 2 | 28µs | 2 | 37µs | # spent 22µs (7+15) within XML::LibXML::Element::BEGIN@1533 which was called:
# once (7µs+15µs) by MARC::File::XML::BEGIN@9 at line 1533 # spent 22µs making 1 call to XML::LibXML::Element::BEGIN@1533
# spent 15µs making 1 call to vars::import |
1534 | 1 | 2µs | @ISA = ('XML::LibXML::Node'); | ||
1535 | 2 | 24µs | 2 | 576µs | # spent 291µs (6+285) within XML::LibXML::Element::BEGIN@1535 which was called:
# once (6µs+285µs) by MARC::File::XML::BEGIN@9 at line 1535 # spent 291µs making 1 call to XML::LibXML::Element::BEGIN@1535
# spent 285µs making 1 call to XML::LibXML::import |
1536 | 2 | 681µs | 1 | 1.63ms | # spent 1.63ms (1.56+71µs) within XML::LibXML::Element::BEGIN@1536 which was called:
# once (1.56ms+71µs) by MARC::File::XML::BEGIN@9 at line 1536 # spent 1.63ms making 1 call to XML::LibXML::Element::BEGIN@1536 |
1537 | 2 | 24µs | 2 | 66µs | # spent 37µs (8+29) within XML::LibXML::Element::BEGIN@1537 which was called:
# once (8µs+29µs) by MARC::File::XML::BEGIN@9 at line 1537 # spent 37µs making 1 call to XML::LibXML::Element::BEGIN@1537
# spent 29µs making 1 call to Exporter::import |
1538 | |||||
1539 | 2 | 36µs | 2 | 48µs | # spent 28µs (9+20) within XML::LibXML::Element::BEGIN@1539 which was called:
# once (9µs+20µs) by MARC::File::XML::BEGIN@9 at line 1539 # spent 28µs making 1 call to XML::LibXML::Element::BEGIN@1539
# spent 20µs making 1 call to Exporter::import |
1540 | |||||
1541 | use overload | ||||
1542 | 1 | 4µs | 1 | 33µs | # spent 39µs (6+33) within XML::LibXML::Element::BEGIN@1542 which was called:
# once (6µs+33µs) by MARC::File::XML::BEGIN@9 at line 1546 # spent 33µs making 1 call to overload::import |
1543 | 'eq' => '_isSameNodeLax', '==' => '_isSameNodeLax', | ||||
1544 | 'ne' => '_isNotSameNodeLax', '!=' => '_isNotSameNodeLax', | ||||
1545 | fallback => 1, | ||||
1546 | 1 | 1.17ms | 1 | 39µs | ; # spent 39µs making 1 call to XML::LibXML::Element::BEGIN@1542 |
1547 | |||||
1548 | sub _isNotSameNodeLax { | ||||
1549 | my ($self, $other) = @_; | ||||
1550 | |||||
1551 | return ((not $self->_isSameNodeLax($other)) ? 1 : ''); | ||||
1552 | } | ||||
1553 | |||||
1554 | sub _isSameNodeLax { | ||||
1555 | my ($self, $other) = @_; | ||||
1556 | |||||
1557 | if (blessed($other) and $other->isa('XML::LibXML::Element')) | ||||
1558 | { | ||||
1559 | return ($self->isSameNode($other) ? 1 : ''); | ||||
1560 | } | ||||
1561 | else | ||||
1562 | { | ||||
1563 | return ''; | ||||
1564 | } | ||||
1565 | } | ||||
1566 | |||||
1567 | { | ||||
1568 | 2 | 600ns | my %tiecache; | ||
1569 | |||||
1570 | sub __destroy_tiecache | ||||
1571 | { | ||||
1572 | delete $tiecache{ 0+$_[0] }; | ||||
1573 | } | ||||
1574 | |||||
1575 | sub getAttributeHash | ||||
1576 | { | ||||
1577 | my $self = shift; | ||||
1578 | if (!exists $tiecache{ 0+$self }) { | ||||
1579 | tie my %attr, 'XML::LibXML::AttributeHash', $self, weaken => 1; | ||||
1580 | $tiecache{ 0+$self } = \%attr; | ||||
1581 | } | ||||
1582 | return $tiecache{ 0+$self }; | ||||
1583 | } | ||||
1584 | sub DESTROY | ||||
1585 | { | ||||
1586 | my ($self) = @_; | ||||
1587 | $self->__destroy_tiecache; | ||||
1588 | $self->SUPER::DESTROY; | ||||
1589 | } | ||||
1590 | } | ||||
1591 | |||||
1592 | sub setNamespace { | ||||
1593 | my $self = shift; | ||||
1594 | my $n = $self->nodeName; | ||||
1595 | if ( $self->_setNamespace(@_) ){ | ||||
1596 | if ( scalar @_ < 3 || $_[2] == 1 ){ | ||||
1597 | $self->setNodeName( $n ); | ||||
1598 | } | ||||
1599 | return 1; | ||||
1600 | } | ||||
1601 | return 0; | ||||
1602 | } | ||||
1603 | |||||
1604 | sub getAttribute { | ||||
1605 | my $self = shift; | ||||
1606 | my $name = $_[0]; | ||||
1607 | if ( $name =~ /^xmlns(?::|$)/ ) { | ||||
1608 | # user wants to get a namespace ... | ||||
1609 | (my $prefix = $name )=~s/^xmlns:?//; | ||||
1610 | $self->_getNamespaceDeclURI($prefix); | ||||
1611 | } | ||||
1612 | else { | ||||
1613 | $self->_getAttribute(@_); | ||||
1614 | } | ||||
1615 | } | ||||
1616 | |||||
1617 | sub setAttribute { | ||||
1618 | my ( $self, $name, $value ) = @_; | ||||
1619 | if ( $name =~ /^xmlns(?::|$)/ ) { | ||||
1620 | # user wants to set the special attribute for declaring XML namespace ... | ||||
1621 | |||||
1622 | # this is fine but not exactly DOM conformant behavior, btw (according to DOM we should | ||||
1623 | # probably declare an attribute which looks like XML namespace declaration | ||||
1624 | # but isn't) | ||||
1625 | (my $nsprefix = $name )=~s/^xmlns:?//; | ||||
1626 | my $nn = $self->nodeName; | ||||
1627 | if ( $nn =~ /^\Q${nsprefix}\E:/ ) { | ||||
1628 | # the element has the same prefix | ||||
1629 | $self->setNamespaceDeclURI($nsprefix,$value) || | ||||
1630 | $self->setNamespace($value,$nsprefix,1); | ||||
1631 | ## | ||||
1632 | ## We set the namespace here. | ||||
1633 | ## This is helpful, as in: | ||||
1634 | ## | ||||
1635 | ## | $e = XML::LibXML::Element->new('foo:bar'); | ||||
1636 | ## | $e->setAttribute('xmlns:foo','http://yoyodine') | ||||
1637 | ## | ||||
1638 | } | ||||
1639 | else { | ||||
1640 | # just modify the namespace | ||||
1641 | $self->setNamespaceDeclURI($nsprefix, $value) || | ||||
1642 | $self->setNamespace($value,$nsprefix,0); | ||||
1643 | } | ||||
1644 | } | ||||
1645 | else { | ||||
1646 | $self->_setAttribute($name, $value); | ||||
1647 | } | ||||
1648 | } | ||||
1649 | |||||
1650 | sub getAttributeNS { | ||||
1651 | my $self = shift; | ||||
1652 | my ($nsURI, $name) = @_; | ||||
1653 | croak("invalid attribute name") if !defined($name) or $name eq q{}; | ||||
1654 | if ( defined($nsURI) and $nsURI eq XML_XMLNS_NS ) { | ||||
1655 | $self->_getNamespaceDeclURI($name eq 'xmlns' ? undef : $name); | ||||
1656 | } | ||||
1657 | else { | ||||
1658 | $self->_getAttributeNS(@_); | ||||
1659 | } | ||||
1660 | } | ||||
1661 | |||||
1662 | sub setAttributeNS { | ||||
1663 | my ($self, $nsURI, $qname, $value)=@_; | ||||
1664 | unless (defined $qname and length $qname) { | ||||
1665 | croak("bad name"); | ||||
1666 | } | ||||
1667 | if (defined($nsURI) and $nsURI eq XML_XMLNS_NS) { | ||||
1668 | if ($qname !~ /^xmlns(?::|$)/) { | ||||
1669 | croak("NAMESPACE ERROR: Namespace declarations must have the prefix 'xmlns'"); | ||||
1670 | } | ||||
1671 | $self->setAttribute($qname,$value); # see implementation above | ||||
1672 | return; | ||||
1673 | } | ||||
1674 | if ($qname=~/:/ and not (defined($nsURI) and length($nsURI))) { | ||||
1675 | croak("NAMESPACE ERROR: Attribute without a prefix cannot be in a namespace"); | ||||
1676 | } | ||||
1677 | if ($qname=~/^xmlns(?:$|:)/) { | ||||
1678 | croak("NAMESPACE ERROR: 'xmlns' prefix and qualified-name are reserved for the namespace ".XML_XMLNS_NS); | ||||
1679 | } | ||||
1680 | if ($qname=~/^xml:/ and not (defined $nsURI and $nsURI eq XML_XML_NS)) { | ||||
1681 | croak("NAMESPACE ERROR: 'xml' prefix is reserved for the namespace ".XML_XML_NS); | ||||
1682 | } | ||||
1683 | $self->_setAttributeNS( defined $nsURI ? $nsURI : undef, $qname, $value ); | ||||
1684 | } | ||||
1685 | |||||
1686 | sub getElementsByTagName { | ||||
1687 | my ( $node , $name ) = @_; | ||||
1688 | my $xpath = $name eq '*' ? "descendant::*" : "descendant::*[name()='$name']"; | ||||
1689 | my @nodes = $node->_findnodes($xpath); | ||||
1690 | return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1691 | } | ||||
1692 | |||||
1693 | sub getElementsByTagNameNS { | ||||
1694 | my ( $node, $nsURI, $name ) = @_; | ||||
1695 | my $xpath; | ||||
1696 | if ( $name eq '*' ) { | ||||
1697 | if ( $nsURI eq '*' ) { | ||||
1698 | $xpath = "descendant::*"; | ||||
1699 | } else { | ||||
1700 | $xpath = "descendant::*[namespace-uri()='$nsURI']"; | ||||
1701 | } | ||||
1702 | } elsif ( $nsURI eq '*' ) { | ||||
1703 | $xpath = "descendant::*[local-name()='$name']"; | ||||
1704 | } else { | ||||
1705 | $xpath = "descendant::*[local-name()='$name' and namespace-uri()='$nsURI']"; | ||||
1706 | } | ||||
1707 | my @nodes = $node->_findnodes($xpath); | ||||
1708 | return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1709 | } | ||||
1710 | |||||
1711 | sub getElementsByLocalName { | ||||
1712 | my ( $node,$name ) = @_; | ||||
1713 | my $xpath; | ||||
1714 | if ($name eq '*') { | ||||
1715 | $xpath = "descendant::*"; | ||||
1716 | } else { | ||||
1717 | $xpath = "descendant::*[local-name()='$name']"; | ||||
1718 | } | ||||
1719 | my @nodes = $node->_findnodes($xpath); | ||||
1720 | return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1721 | } | ||||
1722 | |||||
1723 | sub getChildrenByTagName { | ||||
1724 | my ( $node, $name ) = @_; | ||||
1725 | my @nodes; | ||||
1726 | if ($name eq '*') { | ||||
1727 | @nodes = grep { $_->nodeType == XML_ELEMENT_NODE() } | ||||
1728 | $node->childNodes(); | ||||
1729 | } else { | ||||
1730 | @nodes = grep { $_->nodeName eq $name } $node->childNodes(); | ||||
1731 | } | ||||
1732 | return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1733 | } | ||||
1734 | |||||
1735 | sub getChildrenByLocalName { | ||||
1736 | my ( $node, $name ) = @_; | ||||
1737 | # my @nodes; | ||||
1738 | # if ($name eq '*') { | ||||
1739 | # @nodes = grep { $_->nodeType == XML_ELEMENT_NODE() } | ||||
1740 | # $node->childNodes(); | ||||
1741 | # } else { | ||||
1742 | # @nodes = grep { $_->nodeType == XML_ELEMENT_NODE() and | ||||
1743 | # $_->localName eq $name } $node->childNodes(); | ||||
1744 | # } | ||||
1745 | # return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1746 | my @nodes = $node->_getChildrenByTagNameNS('*',$name); | ||||
1747 | return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1748 | } | ||||
1749 | |||||
1750 | sub getChildrenByTagNameNS { | ||||
1751 | my ( $node, $nsURI, $name ) = @_; | ||||
1752 | my @nodes = $node->_getChildrenByTagNameNS($nsURI,$name); | ||||
1753 | return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); | ||||
1754 | } | ||||
1755 | |||||
1756 | sub appendWellBalancedChunk { | ||||
1757 | my ( $self, $chunk ) = @_; | ||||
1758 | |||||
1759 | my $local_parser = XML::LibXML->new(); | ||||
1760 | my $frag = $local_parser->parse_xml_chunk( $chunk ); | ||||
1761 | |||||
1762 | $self->appendChild( $frag ); | ||||
1763 | } | ||||
1764 | |||||
1765 | 1; | ||||
1766 | |||||
1767 | #-------------------------------------------------------------------------# | ||||
1768 | # XML::LibXML::Text Interface # | ||||
1769 | #-------------------------------------------------------------------------# | ||||
1770 | package XML::LibXML::Text; | ||||
1771 | |||||
1772 | 2 | 189µs | 2 | 45µs | # spent 27µs (8+18) within XML::LibXML::Text::BEGIN@1772 which was called:
# once (8µs+18µs) by MARC::File::XML::BEGIN@9 at line 1772 # spent 27µs making 1 call to XML::LibXML::Text::BEGIN@1772
# spent 18µs making 1 call to vars::import |
1773 | 1 | 2µs | @ISA = ('XML::LibXML::Node'); | ||
1774 | |||||
1775 | sub attributes { return undef; } | ||||
1776 | |||||
1777 | sub deleteDataString { | ||||
1778 | my ($node, $string, $all) = @_; | ||||
1779 | |||||
1780 | return $node->replaceDataString($string, '', $all); | ||||
1781 | } | ||||
1782 | |||||
1783 | sub replaceDataString { | ||||
1784 | my ( $node, $left_proto, $right,$all ) = @_; | ||||
1785 | |||||
1786 | # Assure we exchange the strings and not expressions! | ||||
1787 | my $left = quotemeta($left_proto); | ||||
1788 | |||||
1789 | my $datastr = $node->nodeValue(); | ||||
1790 | if ( $all ) { | ||||
1791 | $datastr =~ s/$left/$right/g; | ||||
1792 | } | ||||
1793 | else{ | ||||
1794 | $datastr =~ s/$left/$right/; | ||||
1795 | } | ||||
1796 | $node->setData( $datastr ); | ||||
1797 | } | ||||
1798 | |||||
1799 | sub replaceDataRegEx { | ||||
1800 | my ( $node, $leftre, $rightre, $flags ) = @_; | ||||
1801 | return unless defined $leftre; | ||||
1802 | $rightre ||= ""; | ||||
1803 | |||||
1804 | my $datastr = $node->nodeValue(); | ||||
1805 | my $restr = "s/" . $leftre . "/" . $rightre . "/"; | ||||
1806 | $restr .= $flags if defined $flags; | ||||
1807 | |||||
1808 | eval '$datastr =~ '. $restr; | ||||
1809 | |||||
1810 | $node->setData( $datastr ); | ||||
1811 | } | ||||
1812 | |||||
1813 | 1; | ||||
1814 | |||||
1815 | package XML::LibXML::Comment; | ||||
1816 | |||||
1817 | 2 | 43µs | 2 | 38µs | # spent 22µs (7+16) within XML::LibXML::Comment::BEGIN@1817 which was called:
# once (7µs+16µs) by MARC::File::XML::BEGIN@9 at line 1817 # spent 22µs making 1 call to XML::LibXML::Comment::BEGIN@1817
# spent 16µs making 1 call to vars::import |
1818 | 1 | 2µs | @ISA = ('XML::LibXML::Text'); | ||
1819 | |||||
1820 | 1; | ||||
1821 | |||||
1822 | package XML::LibXML::CDATASection; | ||||
1823 | |||||
1824 | 2 | 38µs | 2 | 35µs | # spent 21µs (6+14) within XML::LibXML::CDATASection::BEGIN@1824 which was called:
# once (6µs+14µs) by MARC::File::XML::BEGIN@9 at line 1824 # spent 21µs making 1 call to XML::LibXML::CDATASection::BEGIN@1824
# spent 14µs making 1 call to vars::import |
1825 | 1 | 2µs | @ISA = ('XML::LibXML::Text'); | ||
1826 | |||||
1827 | 1; | ||||
1828 | |||||
1829 | #-------------------------------------------------------------------------# | ||||
1830 | # XML::LibXML::Attribute Interface # | ||||
1831 | #-------------------------------------------------------------------------# | ||||
1832 | package XML::LibXML::Attr; | ||||
1833 | 2 | 86µs | 2 | 33µs | # spent 20µs (6+13) within XML::LibXML::Attr::BEGIN@1833 which was called:
# once (6µs+13µs) by MARC::File::XML::BEGIN@9 at line 1833 # spent 20µs making 1 call to XML::LibXML::Attr::BEGIN@1833
# spent 13µs making 1 call to vars::import |
1834 | 1 | 1µs | @ISA = ('XML::LibXML::Node') ; | ||
1835 | |||||
1836 | sub setNamespace { | ||||
1837 | my ($self,$href,$prefix) = @_; | ||||
1838 | my $n = $self->nodeName; | ||||
1839 | if ( $self->_setNamespace($href,$prefix) ) { | ||||
1840 | $self->setNodeName($n); | ||||
1841 | return 1; | ||||
1842 | } | ||||
1843 | |||||
1844 | return 0; | ||||
1845 | } | ||||
1846 | |||||
1847 | 1; | ||||
1848 | |||||
1849 | #-------------------------------------------------------------------------# | ||||
1850 | # XML::LibXML::Dtd Interface # | ||||
1851 | #-------------------------------------------------------------------------# | ||||
1852 | # this is still under construction | ||||
1853 | # | ||||
1854 | package XML::LibXML::Dtd; | ||||
1855 | 2 | 38µs | 2 | 33µs | # spent 19µs (6+14) within XML::LibXML::Dtd::BEGIN@1855 which was called:
# once (6µs+14µs) by MARC::File::XML::BEGIN@9 at line 1855 # spent 19µs making 1 call to XML::LibXML::Dtd::BEGIN@1855
# spent 14µs making 1 call to vars::import |
1856 | 1 | 2µs | @ISA = ('XML::LibXML::Node'); | ||
1857 | |||||
1858 | # at least DESTROY and CLONE_SKIP must be inherited | ||||
1859 | |||||
1860 | 1; | ||||
1861 | |||||
1862 | #-------------------------------------------------------------------------# | ||||
1863 | # XML::LibXML::PI Interface # | ||||
1864 | #-------------------------------------------------------------------------# | ||||
1865 | package XML::LibXML::PI; | ||||
1866 | 2 | 296µs | 2 | 33µs | # spent 19µs (6+13) within XML::LibXML::PI::BEGIN@1866 which was called:
# once (6µs+13µs) by MARC::File::XML::BEGIN@9 at line 1866 # spent 19µs making 1 call to XML::LibXML::PI::BEGIN@1866
# spent 13µs making 1 call to vars::import |
1867 | 1 | 2µs | @ISA = ('XML::LibXML::Node'); | ||
1868 | |||||
1869 | sub setData { | ||||
1870 | my $pi = shift; | ||||
1871 | |||||
1872 | my $string = ""; | ||||
1873 | if ( scalar @_ == 1 ) { | ||||
1874 | $string = shift; | ||||
1875 | } | ||||
1876 | else { | ||||
1877 | my %h = @_; | ||||
1878 | $string = join " ", map {$_.'="'.$h{$_}.'"'} keys %h; | ||||
1879 | } | ||||
1880 | |||||
1881 | # the spec says any char but "?>" [17] | ||||
1882 | $pi->_setData( $string ) unless $string =~ /\?>/; | ||||
1883 | } | ||||
1884 | |||||
1885 | 1; | ||||
1886 | |||||
1887 | #-------------------------------------------------------------------------# | ||||
1888 | # XML::LibXML::Namespace Interface # | ||||
1889 | #-------------------------------------------------------------------------# | ||||
1890 | package XML::LibXML::Namespace; | ||||
1891 | |||||
1892 | sub CLONE_SKIP { 1 } | ||||
1893 | |||||
1894 | # In fact, this is not a node! | ||||
1895 | sub prefix { return "xmlns"; } | ||||
1896 | sub getPrefix { return "xmlns"; } | ||||
1897 | sub getNamespaceURI { return "http://www.w3.org/2000/xmlns/" }; | ||||
1898 | |||||
1899 | sub getNamespaces { return (); } | ||||
1900 | |||||
1901 | sub nodeName { | ||||
1902 | my $self = shift; | ||||
1903 | my $nsP = $self->localname; | ||||
1904 | return ( defined($nsP) && length($nsP) ) ? "xmlns:$nsP" : "xmlns"; | ||||
1905 | } | ||||
1906 | sub name { goto &nodeName } | ||||
1907 | sub getName { goto &nodeName } | ||||
1908 | |||||
1909 | sub isEqualNode { | ||||
1910 | my ( $self, $ref ) = @_; | ||||
1911 | if ( ref($ref) eq "XML::LibXML::Namespace" ) { | ||||
1912 | return $self->_isEqual($ref); | ||||
1913 | } | ||||
1914 | return 0; | ||||
1915 | } | ||||
1916 | |||||
1917 | sub isSameNode { | ||||
1918 | my ( $self, $ref ) = @_; | ||||
1919 | if ( $$self == $$ref ){ | ||||
1920 | return 1; | ||||
1921 | } | ||||
1922 | return 0; | ||||
1923 | } | ||||
1924 | |||||
1925 | 1 | 0s | 1; | ||
1926 | |||||
1927 | #-------------------------------------------------------------------------# | ||||
1928 | # XML::LibXML::NamedNodeMap Interface # | ||||
1929 | #-------------------------------------------------------------------------# | ||||
1930 | package XML::LibXML::NamedNodeMap; | ||||
1931 | |||||
1932 | 2 | 425µs | 2 | 301µs | # spent 154µs (7+147) within XML::LibXML::NamedNodeMap::BEGIN@1932 which was called:
# once (7µs+147µs) by MARC::File::XML::BEGIN@9 at line 1932 # spent 154µs making 1 call to XML::LibXML::NamedNodeMap::BEGIN@1932
# spent 147µs making 1 call to XML::LibXML::import |
1933 | |||||
1934 | sub CLONE_SKIP { | ||||
1935 | return $XML::LibXML::__threads_shared ? 0 : 1; | ||||
1936 | } | ||||
1937 | |||||
1938 | sub new { | ||||
1939 | my $class = shift; | ||||
1940 | my $self = bless { Nodes => [@_] }, $class; | ||||
1941 | $self->{NodeMap} = { map { $_->nodeName => $_ } @_ }; | ||||
1942 | return $self; | ||||
1943 | } | ||||
1944 | |||||
1945 | sub length { return scalar( @{$_[0]->{Nodes}} ); } | ||||
1946 | sub nodes { return $_[0]->{Nodes}; } | ||||
1947 | sub item { $_[0]->{Nodes}->[$_[1]]; } | ||||
1948 | |||||
1949 | sub getNamedItem { | ||||
1950 | my $self = shift; | ||||
1951 | my $name = shift; | ||||
1952 | |||||
1953 | return $self->{NodeMap}->{$name}; | ||||
1954 | } | ||||
1955 | |||||
1956 | sub setNamedItem { | ||||
1957 | my $self = shift; | ||||
1958 | my $node = shift; | ||||
1959 | |||||
1960 | my $retval; | ||||
1961 | if ( defined $node ) { | ||||
1962 | if ( scalar @{$self->{Nodes}} ) { | ||||
1963 | my $name = $node->nodeName(); | ||||
1964 | if ( $node->nodeType() == XML_NAMESPACE_DECL ) { | ||||
1965 | return; | ||||
1966 | } | ||||
1967 | if ( defined $self->{NodeMap}->{$name} ) { | ||||
1968 | if ( $node->isSameNode( $self->{NodeMap}->{$name} ) ) { | ||||
1969 | return; | ||||
1970 | } | ||||
1971 | $retval = $self->{NodeMap}->{$name}->replaceNode( $node ); | ||||
1972 | } | ||||
1973 | else { | ||||
1974 | $self->{Nodes}->[0]->addSibling($node); | ||||
1975 | } | ||||
1976 | |||||
1977 | $self->{NodeMap}->{$name} = $node; | ||||
1978 | push @{$self->{Nodes}}, $node; | ||||
1979 | } | ||||
1980 | else { | ||||
1981 | # not done yet | ||||
1982 | # can this be properly be done??? | ||||
1983 | warn "not done yet\n"; | ||||
1984 | } | ||||
1985 | } | ||||
1986 | return $retval; | ||||
1987 | } | ||||
1988 | |||||
1989 | sub removeNamedItem { | ||||
1990 | my $self = shift; | ||||
1991 | my $name = shift; | ||||
1992 | my $retval; | ||||
1993 | if ( $name =~ /^xmlns/ ) { | ||||
1994 | warn "not done yet\n"; | ||||
1995 | } | ||||
1996 | elsif ( exists $self->{NodeMap}->{$name} ) { | ||||
1997 | $retval = $self->{NodeMap}->{$name}; | ||||
1998 | $retval->unbindNode; | ||||
1999 | delete $self->{NodeMap}->{$name}; | ||||
2000 | $self->{Nodes} = [grep {not($retval->isSameNode($_))} @{$self->{Nodes}}]; | ||||
2001 | } | ||||
2002 | |||||
2003 | return $retval; | ||||
2004 | } | ||||
2005 | |||||
2006 | sub getNamedItemNS { | ||||
2007 | my $self = shift; | ||||
2008 | my $nsURI = shift; | ||||
2009 | my $name = shift; | ||||
2010 | return undef; | ||||
2011 | } | ||||
2012 | |||||
2013 | sub setNamedItemNS { | ||||
2014 | my $self = shift; | ||||
2015 | my $nsURI = shift; | ||||
2016 | my $node = shift; | ||||
2017 | return undef; | ||||
2018 | } | ||||
2019 | |||||
2020 | sub removeNamedItemNS { | ||||
2021 | my $self = shift; | ||||
2022 | my $nsURI = shift; | ||||
2023 | my $name = shift; | ||||
2024 | return undef; | ||||
2025 | } | ||||
2026 | |||||
2027 | 1; | ||||
2028 | |||||
2029 | package XML::LibXML::_SAXParser; | ||||
2030 | |||||
2031 | # this is pseudo class!!! and it will be removed as soon all functions | ||||
2032 | # moved to XS level | ||||
2033 | |||||
2034 | 2 | 496µs | 1 | 7µs | # spent 7µs within XML::LibXML::_SAXParser::BEGIN@2034 which was called:
# once (7µs+0s) by MARC::File::XML::BEGIN@9 at line 2034 # spent 7µs making 1 call to XML::LibXML::_SAXParser::BEGIN@2034 |
2035 | |||||
2036 | sub CLONE_SKIP { | ||||
2037 | return $XML::LibXML::__threads_shared ? 0 : 1; | ||||
2038 | } | ||||
2039 | |||||
2040 | # these functions will use SAX exceptions as soon i know how things really work | ||||
2041 | sub warning { | ||||
2042 | my ( $parser, $message, $line, $col ) = @_; | ||||
2043 | my $error = XML::SAX::Exception::Parse->new( LineNumber => $line, | ||||
2044 | ColumnNumber => $col, | ||||
2045 | Message => $message, ); | ||||
2046 | $parser->{HANDLER}->warning( $error ); | ||||
2047 | } | ||||
2048 | |||||
2049 | sub error { | ||||
2050 | my ( $parser, $message, $line, $col ) = @_; | ||||
2051 | |||||
2052 | my $error = XML::SAX::Exception::Parse->new( LineNumber => $line, | ||||
2053 | ColumnNumber => $col, | ||||
2054 | Message => $message, ); | ||||
2055 | $parser->{HANDLER}->error( $error ); | ||||
2056 | } | ||||
2057 | |||||
2058 | sub fatal_error { | ||||
2059 | my ( $parser, $message, $line, $col ) = @_; | ||||
2060 | my $error = XML::SAX::Exception::Parse->new( LineNumber => $line, | ||||
2061 | ColumnNumber => $col, | ||||
2062 | Message => $message, ); | ||||
2063 | $parser->{HANDLER}->fatal_error( $error ); | ||||
2064 | } | ||||
2065 | |||||
2066 | 1 | 0s | 1; | ||
2067 | |||||
2068 | package XML::LibXML::RelaxNG; | ||||
2069 | |||||
2070 | sub CLONE_SKIP { 1 } | ||||
2071 | |||||
2072 | sub new { | ||||
2073 | my $class = shift; | ||||
2074 | my %args = @_; | ||||
2075 | |||||
2076 | my $self = undef; | ||||
2077 | if ( defined $args{location} ) { | ||||
2078 | $self = $class->parse_location( $args{location} ); | ||||
2079 | } | ||||
2080 | elsif ( defined $args{string} ) { | ||||
2081 | $self = $class->parse_buffer( $args{string} ); | ||||
2082 | } | ||||
2083 | elsif ( defined $args{DOM} ) { | ||||
2084 | $self = $class->parse_document( $args{DOM} ); | ||||
2085 | } | ||||
2086 | |||||
2087 | return $self; | ||||
2088 | } | ||||
2089 | |||||
2090 | 1; | ||||
2091 | |||||
2092 | package XML::LibXML::Schema; | ||||
2093 | |||||
2094 | sub CLONE_SKIP { 1 } | ||||
2095 | |||||
2096 | sub new { | ||||
2097 | my $class = shift; | ||||
2098 | my %args = @_; | ||||
2099 | |||||
2100 | my $self = undef; | ||||
2101 | if ( defined $args{location} ) { | ||||
2102 | $self = $class->parse_location( $args{location} ); | ||||
2103 | } | ||||
2104 | elsif ( defined $args{string} ) { | ||||
2105 | $self = $class->parse_buffer( $args{string} ); | ||||
2106 | } | ||||
2107 | |||||
2108 | return $self; | ||||
2109 | } | ||||
2110 | |||||
2111 | 1 | 0s | 1; | ||
2112 | |||||
2113 | #-------------------------------------------------------------------------# | ||||
2114 | # XML::LibXML::Pattern Interface # | ||||
2115 | #-------------------------------------------------------------------------# | ||||
2116 | |||||
2117 | package XML::LibXML::Pattern; | ||||
2118 | |||||
2119 | sub CLONE_SKIP { 1 } | ||||
2120 | |||||
2121 | sub new { | ||||
2122 | my $class = shift; | ||||
2123 | my ($pattern,$ns_map)=@_; | ||||
2124 | my $self = undef; | ||||
2125 | |||||
2126 | unless (UNIVERSAL::can($class,'_compilePattern')) { | ||||
2127 | croak("Cannot create XML::LibXML::Pattern - ". | ||||
2128 | "your libxml2 is compiled without pattern support!"); | ||||
2129 | } | ||||
2130 | |||||
2131 | if (ref($ns_map) eq 'HASH') { | ||||
2132 | # translate prefix=>URL hash to a (URL,prefix) list | ||||
2133 | $self = $class->_compilePattern($pattern,0,[reverse %$ns_map]); | ||||
2134 | } else { | ||||
2135 | $self = $class->_compilePattern($pattern,0); | ||||
2136 | } | ||||
2137 | return $self; | ||||
2138 | } | ||||
2139 | |||||
2140 | 1; | ||||
2141 | |||||
2142 | #-------------------------------------------------------------------------# | ||||
2143 | # XML::LibXML::RegExp Interface # | ||||
2144 | #-------------------------------------------------------------------------# | ||||
2145 | |||||
2146 | package XML::LibXML::RegExp; | ||||
2147 | |||||
2148 | sub CLONE_SKIP { 1 } | ||||
2149 | |||||
2150 | sub new { | ||||
2151 | my $class = shift; | ||||
2152 | my ($regexp)=@_; | ||||
2153 | unless (UNIVERSAL::can($class,'_compile')) { | ||||
2154 | croak("Cannot create XML::LibXML::RegExp - ". | ||||
2155 | "your libxml2 is compiled without regexp support!"); | ||||
2156 | } | ||||
2157 | return $class->_compile($regexp); | ||||
2158 | } | ||||
2159 | |||||
2160 | 1 | 100ns | 1; | ||
2161 | |||||
2162 | #-------------------------------------------------------------------------# | ||||
2163 | # XML::LibXML::XPathExpression Interface # | ||||
2164 | #-------------------------------------------------------------------------# | ||||
2165 | |||||
2166 | package XML::LibXML::XPathExpression; | ||||
2167 | |||||
2168 | sub CLONE_SKIP { 1 } | ||||
2169 | |||||
2170 | 1; | ||||
2171 | |||||
2172 | |||||
2173 | #-------------------------------------------------------------------------# | ||||
2174 | # XML::LibXML::InputCallback Interface # | ||||
2175 | #-------------------------------------------------------------------------# | ||||
2176 | package XML::LibXML::InputCallback; | ||||
2177 | |||||
2178 | 2 | 48µs | 2 | 97µs | # spent 52µs (6+45) within XML::LibXML::InputCallback::BEGIN@2178 which was called:
# once (6µs+45µs) by MARC::File::XML::BEGIN@9 at line 2178 # spent 52µs making 1 call to XML::LibXML::InputCallback::BEGIN@2178
# spent 45µs making 1 call to vars::import |
2179 | |||||
2180 | # spent 4µs within XML::LibXML::InputCallback::BEGIN@2180 which was called:
# once (4µs+0s) by MARC::File::XML::BEGIN@9 at line 2186 | ||||
2181 | 1 | 200ns | $_CUR_CB = undef; | ||
2182 | 1 | 400ns | @_GLOBAL_CALLBACKS = (); | ||
2183 | 1 | 100ns | @_CB_STACK = (); | ||
2184 | 1 | 200ns | $_CB_NESTED_DEPTH = 0; | ||
2185 | 1 | 4µs | @_CB_NESTED_STACK = (); | ||
2186 | 1 | 592µs | 1 | 4µs | } # spent 4µs making 1 call to XML::LibXML::InputCallback::BEGIN@2180 |
2187 | |||||
2188 | sub CLONE_SKIP { | ||||
2189 | return $XML::LibXML::__threads_shared ? 0 : 1; | ||||
2190 | } | ||||
2191 | |||||
2192 | #-------------------------------------------------------------------------# | ||||
2193 | # global callbacks # | ||||
2194 | #-------------------------------------------------------------------------# | ||||
2195 | sub _callback_match { | ||||
2196 | my $uri = shift; | ||||
2197 | my $retval = 0; | ||||
2198 | |||||
2199 | # loop through the callbacks, and find the first matching one. | ||||
2200 | # The callbacks are stored in execution order (reverse stack order). | ||||
2201 | # Any new global callbacks are shifted to the callback stack. | ||||
2202 | foreach my $cb ( @_GLOBAL_CALLBACKS ) { | ||||
2203 | |||||
2204 | # callbacks have to return 1, 0 or undef, while 0 and undef | ||||
2205 | # are handled the same way. | ||||
2206 | # in fact, if callbacks return other values, the global match | ||||
2207 | # assumes silently that the callback failed. | ||||
2208 | |||||
2209 | $retval = $cb->[0]->($uri); | ||||
2210 | |||||
2211 | if ( defined $retval and $retval == 1 ) { | ||||
2212 | # make the other callbacks use this callback | ||||
2213 | $_CUR_CB = $cb; | ||||
2214 | unshift @_CB_STACK, $cb; | ||||
2215 | last; | ||||
2216 | } | ||||
2217 | } | ||||
2218 | |||||
2219 | return $retval; | ||||
2220 | } | ||||
2221 | |||||
2222 | sub _callback_open { | ||||
2223 | my $uri = shift; | ||||
2224 | my $retval = undef; | ||||
2225 | |||||
2226 | # the open callback has to return a defined value. | ||||
2227 | # if one works on files this can be a file handle. But | ||||
2228 | # depending on the needs of the callback it also can be a | ||||
2229 | # database handle or a integer labeling a certain dataset. | ||||
2230 | |||||
2231 | if ( defined $_CUR_CB ) { | ||||
2232 | $retval = $_CUR_CB->[1]->( $uri ); | ||||
2233 | |||||
2234 | # reset the callbacks, if one callback cannot open an uri | ||||
2235 | if ( not defined $retval or $retval == 0 ) { | ||||
2236 | shift @_CB_STACK; | ||||
2237 | $_CUR_CB = $_CB_STACK[0]; | ||||
2238 | } | ||||
2239 | } | ||||
2240 | |||||
2241 | return $retval; | ||||
2242 | } | ||||
2243 | |||||
2244 | sub _callback_read { | ||||
2245 | my $fh = shift; | ||||
2246 | my $buflen = shift; | ||||
2247 | |||||
2248 | my $retval = undef; | ||||
2249 | |||||
2250 | if ( defined $_CUR_CB ) { | ||||
2251 | $retval = $_CUR_CB->[2]->( $fh, $buflen ); | ||||
2252 | } | ||||
2253 | |||||
2254 | return $retval; | ||||
2255 | } | ||||
2256 | |||||
2257 | sub _callback_close { | ||||
2258 | my $fh = shift; | ||||
2259 | my $retval = 0; | ||||
2260 | |||||
2261 | if ( defined $_CUR_CB ) { | ||||
2262 | $retval = $_CUR_CB->[3]->( $fh ); | ||||
2263 | shift @_CB_STACK; | ||||
2264 | $_CUR_CB = $_CB_STACK[0]; | ||||
2265 | } | ||||
2266 | |||||
2267 | return $retval; | ||||
2268 | } | ||||
2269 | |||||
2270 | #-------------------------------------------------------------------------# | ||||
2271 | # member functions and methods # | ||||
2272 | #-------------------------------------------------------------------------# | ||||
2273 | |||||
2274 | sub new { | ||||
2275 | my $CLASS = shift; | ||||
2276 | return bless {'_CALLBACKS' => []}, $CLASS; | ||||
2277 | } | ||||
2278 | |||||
2279 | # add a callback set to the callback stack | ||||
2280 | # synopsis: $icb->register_callbacks( [$match_cb, $open_cb, $read_cb, $close_cb] ); | ||||
2281 | sub register_callbacks { | ||||
2282 | my $self = shift; | ||||
2283 | my $cbset = shift; | ||||
2284 | |||||
2285 | # test if callback set is complete | ||||
2286 | if ( ref $cbset eq "ARRAY" and scalar( @$cbset ) == 4 ) { | ||||
2287 | unshift @{$self->{_CALLBACKS}}, $cbset; | ||||
2288 | } | ||||
2289 | } | ||||
2290 | |||||
2291 | # remove a callback set to the callback stack | ||||
2292 | # if a callback set is passed, this function will check for the match function | ||||
2293 | sub unregister_callbacks { | ||||
2294 | my $self = shift; | ||||
2295 | my $cbset = shift; | ||||
2296 | if ( ref $cbset eq "ARRAY" and scalar( @$cbset ) == 4 ) { | ||||
2297 | $self->{_CALLBACKS} = [grep { $_->[0] != $cbset->[0] } @{$self->{_CALLBACKS}}]; | ||||
2298 | } | ||||
2299 | else { | ||||
2300 | shift @{$self->{_CALLBACKS}}; | ||||
2301 | } | ||||
2302 | } | ||||
2303 | |||||
2304 | # make libxml2 use the callbacks | ||||
2305 | sub init_callbacks { | ||||
2306 | my $self = shift; | ||||
2307 | my $parser = shift; | ||||
2308 | |||||
2309 | #initialize the libxml2 callbacks unless this is a nested callback | ||||
2310 | $self->lib_init_callbacks() unless($_CB_NESTED_DEPTH); | ||||
2311 | |||||
2312 | #store the callbacks for any outer executing parser instance | ||||
2313 | $_CB_NESTED_DEPTH++; | ||||
2314 | push @_CB_NESTED_STACK, [ | ||||
2315 | $_CUR_CB, | ||||
2316 | [@_CB_STACK], | ||||
2317 | [@_GLOBAL_CALLBACKS], | ||||
2318 | ]; | ||||
2319 | |||||
2320 | #initialize the callback variables for the current parser | ||||
2321 | $_CUR_CB = undef; | ||||
2322 | @_CB_STACK = (); | ||||
2323 | @_GLOBAL_CALLBACKS = @{ $self->{_CALLBACKS} }; | ||||
2324 | |||||
2325 | #attach parser specific callbacks | ||||
2326 | if($parser) { | ||||
2327 | my $mcb = $parser->match_callback(); | ||||
2328 | my $ocb = $parser->open_callback(); | ||||
2329 | my $rcb = $parser->read_callback(); | ||||
2330 | my $ccb = $parser->close_callback(); | ||||
2331 | if ( defined $mcb and defined $ocb and defined $rcb and defined $ccb ) { | ||||
2332 | unshift @_GLOBAL_CALLBACKS, [$mcb, $ocb, $rcb, $ccb]; | ||||
2333 | } | ||||
2334 | } | ||||
2335 | |||||
2336 | #attach global callbacks | ||||
2337 | if ( defined $XML::LibXML::match_cb and | ||||
2338 | defined $XML::LibXML::open_cb and | ||||
2339 | defined $XML::LibXML::read_cb and | ||||
2340 | defined $XML::LibXML::close_cb ) { | ||||
2341 | push @_GLOBAL_CALLBACKS, [$XML::LibXML::match_cb, | ||||
2342 | $XML::LibXML::open_cb, | ||||
2343 | $XML::LibXML::read_cb, | ||||
2344 | $XML::LibXML::close_cb]; | ||||
2345 | } | ||||
2346 | } | ||||
2347 | |||||
2348 | # reset libxml2's callbacks | ||||
2349 | sub cleanup_callbacks { | ||||
2350 | my $self = shift; | ||||
2351 | |||||
2352 | #restore the callbacks for the outer parser instance | ||||
2353 | $_CB_NESTED_DEPTH--; | ||||
2354 | my $saved = pop @_CB_NESTED_STACK; | ||||
2355 | $_CUR_CB = $saved->[0]; | ||||
2356 | @_CB_STACK = (@{$saved->[1]}); | ||||
2357 | @_GLOBAL_CALLBACKS = (@{$saved->[2]}); | ||||
2358 | |||||
2359 | #clean up the libxml2 callbacks unless there are still outer parsing instances | ||||
2360 | $self->lib_cleanup_callbacks() unless($_CB_NESTED_DEPTH); | ||||
2361 | } | ||||
2362 | |||||
2363 | 1 | 100ns | $XML::LibXML::__loaded=1; | ||
2364 | |||||
2365 | 1 | 15µs | 1; | ||
2366 | |||||
2367 | __END__ | ||||
sub XML::LibXML::CORE:match; # opcode | |||||
# spent 28µs within XML::LibXML::END which was called:
# once (28µs+0s) by main::RUNTIME at line 131 of C4/Service.pm | |||||
# spent 13µs within XML::LibXML::LIBXML_RUNTIME_VERSION which was called:
# once (13µs+0s) by MARC::File::XML::BEGIN@9 at line 224 | |||||
# spent 4µs within XML::LibXML::LIBXML_VERSION which was called:
# once (4µs+0s) by MARC::File::XML::BEGIN@9 at line 225 | |||||
# spent 1.72ms within XML::LibXML::bootstrap which was called:
# once (1.72ms+0s) by DynaLoader::bootstrap at line 210 of DynaLoader.pm |