The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 4684
LICENSE 44
MANIFEST 21
META.json 514
META.yml 1622
Makefile.PL 2921
README 24
lib/XML/MyXML/II.pm 8730
lib/XML/MyXML.pm 180154
t/01.t 24151
t/02.t 1320
11 files changed (This is a version diff) 1313455
@@ -1,5 +1,44 @@
 Revision history for XML-MyXML
 
+0.9007  2015-05-26
+        Add "provides" clause in META.yml, META.json files
+
+0.9006  2014-07-06
+        Replaced Test::Deep::cmp_deeply with Test::More::is_deeply
+        Removed the only non-core dependency from the prereqs (Test::Deep)
+
+0.9005  2014-06-24
+        Fixed bug where just $obj->path('/root-tag') wouldn't return the root element
+
+0.9004  2014-06-24
+        The path parameter of the $obj->path method can now also include the root element inside it, if preceeded with a slash
+            e.g. $obj->path('/root-tag/child-tag/grandchild-tag')
+
+0.9003  2014-06-15
+        On error, all functions now 'croak' rather than 'confess'
+
+0.9002  2014-04-11
+        Improved documentation, with an example
+        Fixed documentation (added 'xml_escape' in the list of exportable methods)
+
+0.9001  2014-03-04
+        Made Changes file compliant
+        Fixed bug where it wasn't possible to have two entities resolving to the same string
+
+0.9000  2014-03-04
+        BREAKING CHANGES:
+        XML::MyXML has changed to work like XML::MyXML::II. This means:
+            Better unicode support (all strings except XML docs themselves, will contain characters instead of bytes/octets)
+            Removed the 'utf8' and 'soft' options from methods and functions that used them
+            Created objects that go out of scope are automatically destroyed (and also removed the $obj->delete method)
+            $obj->tag doesn't by default strip the namespace from the returned tagname
+            XML::MyXML::II doesn't exist anymore
+        Also fixed the rare double-decoding bug (bug #1 on github)
+        The interface looks stable, so preparing for v1.0 release
+
+0.1003  2014-02-01
+        Issue a warning if a user uses XML::MyXML instead of XML::MyXML::II
+
 0.1002  2013-09-10
         Made it compatible with Perl 5.8 again
 
@@ -46,157 +85,156 @@ Revision history for XML-MyXML
 0.0987  2013-03-11
         Switched to Dist::Zilla
 
-0.0986  Oct 8th, 2007
+0.0986  2007-10-08
         Added the ->parent() method
 
-0.09851 Sep 7th, 2007
+0.09851 2007-09-07
         Deleted a duplicate sentence from the documentation
 
-0.0985  Sep 5th, 2007
+0.0985  2007-09-05
         If $obj->attr is called without parameters, will return a hash of all attribute => value pairs
 
-0.098061 Aug 10th, 2007
+0.098061 2007-08-10
         Minor modification in the documentation to describe change in version 0.09806
 
-0.09806 Aug 10th, 2007
+0.09806 2007-08-10
         XML documents to be parsed may be encoded either in UTF-8 or in some other encoding provided this encoding is declared in the XML declaration ( <?xml ... encoding="..." ?> ) in the beginning of the document
 
-0.09805 Jul 27th, 2007
+0.09805 2007-07-27
         Slight improvements to the $obj->delete method and to garbage-colection throughout the module
 
-0.098   Jul 26th, 2007
+0.098   2007-07-26
         Added the $obj->delete method that will clear the memory of an object (needed because an object and its children refer to each other circularly)
 
-0.09766 Apr 17th, 2007
+0.09766 2007-04-17
         All functions that parse XML strings will convert string to utf8 if a different encoding is declared in the XML declaration
 
-0.09765 Apr 17th, 2007
+0.09765 2007-04-17
         Fixed dependencies so tests don't fail
 
-0.09762 Apr 16th, 2007
+0.09762 2007-04-16
         Some functions now check whether the provided XML is valid utf-8, and produce an error if it's not (having 'soft' flag turned on will return undef in case of invalid utf-8)
 
-0.09761 Apr 16th, 2007
+0.09761 2007-04-16
         Removed some debugging code
 
-0.0976  Apr 16th, 2007
+0.0976  2007-04-16
         Fixed encoding issues completely. All strings output by this module are in bytes, unless the 'utf8' flag is used (see this module's documentation)
 
-0.0975  Apr 16th, 2007
+0.0975  2007-04-16
         Fixed encoding issue
 
-0.0974  Apr 16th, 2007
+0.0974  2007-04-16
         Fixed encoding issue
 
-0.0973  Apr 15th, 2007
+0.0973  2007-04-15
         Fixed a critical bug where calling the 'value' method on an empty element would change its contents
 
-0.0972  Apr 12th, 2007
+0.0972  2007-04-12
         Added myperl.eu mention in docs
 
-0.0971  Apr 1st, 2007
+0.0971  2007-04-01
         Fixed bug where simple arrayref structures would get 'consumed' by &simple_to_xml
 
-0.097   Mar 24th, 2007
+0.097   2007-03-24
         &simple_to_xml can add xslt declarations in the beginning
         &xml_to_simple and ->simplify can create arrayrefs in addition to hashrefs (arrayrefs preserve order and duplicate elements)
         Fixed bug where &xml_to_object would choke with some symbols in utf8::upgrade'd XML strings
 
-0.0969  Mar 17th, 2007
+0.0969  2007-03-17
         Fixed bug where simple_to_xml wouldn't accept attributes at the root element
         Fixed XML version in declaration from 1.1 to 1.0
 
-0.0968  Mar 9th, 2007
+0.0968  2007-03-09
         Added the 'strip_ns' flag, that strips namespaces from tags, on &xml_to_simple and on ->simplify
 
-0.0961  Mar 7th, 2007
+0.0961  2007-03-07
         Corrected bug where the indentstring flag on &simple_to_xml wouldn't do anything
 
-0.096   Mar 6th, 2007
+0.096   2007-03-06
         Added ability for the following functions/methods to save their XML output to a file: &tidy_xml, &object_to_xml, &simple_to_xml, ->to_xml, ->to_tidy_xml
         Added the 'soft' flag to &tidy_xml
 
-0.0951  Mar 6th, 2007
+0.0951  2007-03-06
         Corrected bug where ->value would double-decode
 
-0.095   Mar 6th, 2007
+0.095   2007-03-06
         Added support for parsing the simplest and non-recursive form of <!ENTITY> markup
         Added optional 'tidy' flag to &object_to_xml, &simple_to_xml and ->to_xml
         Corrected bug where hex numerical entities couldn't contain capital letters ('A'..'F')
 
-0.094   Mar 6th, 2007
+0.094   2007-03-06
         Added a space before the '?>' mark in the XML declaration introduced in 0.093
         Corrected small bits in documentation
 
-0.093   Mar 5th, 2007
+0.093   2007-03-05
         Parser will now ignore all special markup instead of dying on it (except for CDATA sections which it can handle since v0.061)
         XML documents produced with this module may now have an XML declaration in the beginning (<?xml ... ?>)
         Almost all functions and methods accept flags now
         Wrote features & limitations in the documentation
         Wrote a 'function flags' section in the documentation
 
-0.092   Mar 5th, 2007
+0.092   2007-03-05
         check_xml, which used to be able to check XML strings only, can now check XML files also
         Added an optional 'soft' mode to xml_to_simple and xml_to_object functions, which returns undef instead of dying in case of error
         Added the :all export tag - imports all exportable functions
 
-0.091   Mar 4th, 2007
+0.091   2007-03-04
         xml_to_simple and xml_to_object can now accept a filename for an argument
         Minor alterations in the documentation
 
-0.09    Mar 3rd, 2007
+0.09    2007-03-03
         simple_to_xml($simple_ref) has been changed to allow the argument to be a hashref, an arrayref or a mixed structure
 
-0.083   Mar 3rd, 2007
+0.083   2007-03-03
         Changed the way that flags are set. Instead of a string such as 'strip internal', it's with a hashref { strip => 1, internal => 1 }. Module stops execution and informs about the change, if programmer tries to set flags with the old way.
 
-0.082   Mar 3rd, 2007
+0.082   2007-03-03
         Added optional 'strip' mode for the &xml_to_simple function and the $obj->simplify method, that strips surrounding whitespace from texts
         Added optional 'internal' mode for the $obj->simplify method, that return a hashref only of the contents of the top element
 
-0.081   Mar 3rd, 2007
+0.081   2007-03-03
         Added an 'internal' mode for the &xml_to_simple function
         Added a 'strip' mode for the ->value method that strips surrounding whitespace
 
-0.08    Mar 1st, 2007
+0.08    2007-03-01
         XML-decodes the attribute values when parsing documents, and XML-encodes them when creating XML documents
         Added the ->tag method to XML objects, which retrieves the tag name of the top element
         Minor changes in the documentation
 
-0.076   Feb 27th, 2007
+0.076   2007-02-27
         $element->value returns empty string ('') if element is empty, instead of null
 
-0.075   Feb 25th, 2007
+0.075   2007-02-25
         Added the ->attr('attr_name') method to XML objects, which retrieves the value of an attribute
 
-0.07    Feb 25th, 2007
+0.07    2007-02-25
         Added a check_xml function that checks if the provided XML document is valid enough for use with this module
 
-0.066   Feb 25th, 2007
+0.066   2007-02-25
         Allows whitespace and comments to exist before the root element
 
-0.065   Feb 25th, 2007
+0.065   2007-02-25
         Handles attributes in tags better (attrs are allowed to contain spaces)
 
-0.0641  Feb 25th, 2007
+0.0641  2007-02-25
         Now handles XML comments when parsing XML documents
 
-0.061   Nov 27th, 2006
+0.061   2006-11-27
         Added parsing of CDATA sections
         Added $object->to_xml and $object->to_tidy_xml methods
 
-0.051   Nov 26th, 2006
+0.051   2006-11-26
         Understands numerical (dec and hex) entities in XML (eg &#x20ac; and &#161;)
 
-0.05    Nov 26th, 2006
+0.05    2006-11-26
         Added $obj->simplify method
 
-0.04    Nov 25th, 2006
+0.04    2006-11-25
         Added xml_to_simple function
 
-0.03    May 12th, 2006
+0.03    2006-05-12
         Applied some encoding/decoding commands in several functions
 
-0.01    May 3rd, 2006
+0.01    2006-05-03
         First version, released on an unsuspecting world.
-
@@ -1,4 +1,4 @@
-This software is copyright (c) 2013 by Alexander Karelas.
+This software is copyright (c) 2014 by Alexander Karelas.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
@@ -12,7 +12,7 @@ b) the "Artistic License"
 
 --- The GNU General Public License, Version 1, February 1989 ---
 
-This software is Copyright (c) 2013 by Alexander Karelas.
+This software is Copyright (c) 2014 by Alexander Karelas.
 
 This is free software, licensed under:
 
@@ -22,7 +22,7 @@ This is free software, licensed under:
                      Version 1, February 1989
 
  Copyright (C) 1989 Free Software Foundation, Inc.
- 51 Franklin St, Suite 500, Boston, MA  02110-1335  USA
+ 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
@@ -272,7 +272,7 @@ That's all there is to it!
 
 --- The Artistic License 1.0 ---
 
-This software is Copyright (c) 2013 by Alexander Karelas.
+This software is Copyright (c) 2014 by Alexander Karelas.
 
 This is free software, licensed under:
 
@@ -1,3 +1,4 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020.
 Changes
 LICENSE
 MANIFEST
@@ -6,6 +7,4 @@ META.yml
 Makefile.PL
 README
 lib/XML/MyXML.pm
-lib/XML/MyXML/II.pm
 t/01.t
-t/02.t
@@ -1,10 +1,10 @@
 {
    "abstract" : "A simple-to-use XML module, for parsing and creating XML documents",
    "author" : [
-      "Alexander Karelas <karjala@cpan.org>"
+      "Alexander Karelas <karjala@karjala.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 4.300036, CPAN::Meta::Converter version 2.132140",
+   "generated_by" : "Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142690",
    "license" : [
       "perl_5"
    ],
@@ -16,7 +16,7 @@
    "prereqs" : {
       "configure" : {
          "requires" : {
-            "ExtUtils::MakeMaker" : "6.30"
+            "ExtUtils::MakeMaker" : "0"
          }
       },
       "runtime" : {
@@ -34,11 +34,20 @@
       "test" : {
          "requires" : {
             "File::Temp" : "0",
-            "Test::Deep" : "0",
             "Test::More" : "0"
          }
       }
    },
+   "provides" : {
+      "XML::MyXML" : {
+         "file" : "lib/XML/MyXML.pm",
+         "version" : "0.9007"
+      },
+      "XML::MyXML::Object" : {
+         "file" : "lib/XML/MyXML.pm",
+         "version" : "0.9007"
+      }
+   },
    "release_status" : "stable",
    "resources" : {
       "bugtracker" : {
@@ -51,6 +60,6 @@
          "web" : "https://github.com/akarelas/xml-myxml"
       }
    },
-   "version" : "0.1002"
+   "version" : "0.9007"
 }
 
@@ -1,31 +1,37 @@
 ---
 abstract: 'A simple-to-use XML module, for parsing and creating XML documents'
 author:
-  - 'Alexander Karelas <karjala@cpan.org>'
+  - 'Alexander Karelas <karjala@karjala.org>'
 build_requires:
-  File::Temp: 0
-  Test::Deep: 0
-  Test::More: 0
+  File::Temp: '0'
+  Test::More: '0'
 configure_requires:
-  ExtUtils::MakeMaker: 6.30
+  ExtUtils::MakeMaker: '0'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 4.300036, CPAN::Meta::Converter version 2.132140'
+generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142690'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
+  version: '1.4'
 name: XML-MyXML
+provides:
+  XML::MyXML:
+    file: lib/XML/MyXML.pm
+    version: '0.9007'
+  XML::MyXML::Object:
+    file: lib/XML/MyXML.pm
+    version: '0.9007'
 requires:
-  Carp: 0
-  Encode: 0
-  Exporter: 0
-  Scalar::Util: 0
-  perl: 5.008
-  strict: 0
-  utf8: 0
-  warnings: 0
+  Carp: '0'
+  Encode: '0'
+  Exporter: '0'
+  Scalar::Util: '0'
+  perl: '5.008'
+  strict: '0'
+  utf8: '0'
+  warnings: '0'
 resources:
   bugtracker: https://github.com/akarelas/xml-myxml/issues
   homepage: https://github.com/akarelas/xml-myxml
   repository: https://github.com/akarelas/xml-myxml.git
-version: 0.1002
+version: '0.9007'
@@ -1,19 +1,19 @@
 
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.020.
 use strict;
 use warnings;
 
 use 5.008;
 
-use ExtUtils::MakeMaker 6.30;
+use ExtUtils::MakeMaker ;
 
 
 
 my %WriteMakefileArgs = (
   "ABSTRACT" => "A simple-to-use XML module, for parsing and creating XML documents",
-  "AUTHOR" => "Alexander Karelas <karjala\@cpan.org>",
-  "BUILD_REQUIRES" => {},
+  "AUTHOR" => "Alexander Karelas <karjala\@karjala.org>",
   "CONFIGURE_REQUIRES" => {
-    "ExtUtils::MakeMaker" => "6.30"
+    "ExtUtils::MakeMaker" => 0
   },
   "DISTNAME" => "XML-MyXML",
   "EXE_FILES" => [],
@@ -30,40 +30,32 @@ my %WriteMakefileArgs = (
   },
   "TEST_REQUIRES" => {
     "File::Temp" => 0,
-    "Test::Deep" => 0,
     "Test::More" => 0
   },
-  "VERSION" => "0.1002",
+  "VERSION" => "0.9007",
   "test" => {
     "TESTS" => "t/*.t"
   }
 );
 
 
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
-  my $tr = delete $WriteMakefileArgs{TEST_REQUIRES};
-  my $br = $WriteMakefileArgs{BUILD_REQUIRES};
-  for my $mod ( keys %$tr ) {
-    if ( exists $br->{$mod} ) {
-      $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
-    }
-    else {
-      $br->{$mod} = $tr->{$mod};
-    }
-  }
-}
+my %FallbackPrereqs = (
+  "Carp" => 0,
+  "Encode" => 0,
+  "Exporter" => 0,
+  "File::Temp" => 0,
+  "Scalar::Util" => 0,
+  "Test::More" => 0,
+  "strict" => 0,
+  "utf8" => 0,
+  "warnings" => 0
+);
 
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
-  my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
-  my $pp = $WriteMakefileArgs{PREREQ_PM};
-  for my $mod ( keys %$br ) {
-    if ( exists $pp->{$mod} ) {
-      $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
-    }
-    else {
-      $pp->{$mod} = $br->{$mod};
-    }
-  }
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+  delete $WriteMakefileArgs{TEST_REQUIRES};
+  delete $WriteMakefileArgs{BUILD_REQUIRES};
+  $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
 }
 
 delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
@@ -1,13 +1,15 @@
 
 
 This archive contains the distribution XML-MyXML,
-version 0.1002:
+version 0.9007:
 
   A simple-to-use XML module, for parsing and creating XML documents
 
-This software is copyright (c) 2013 by Alexander Karelas.
+This software is copyright (c) 2014 by Alexander Karelas.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 
+This README file was generated by Dist::Zilla::Plugin::Readme v5.020.
+
@@ -1,873 +0,0 @@
-package XML::MyXML::II;
-{
-  $XML::MyXML::II::VERSION = '0.1002';
-}
-# ABSTRACT: A simple-to-use XML module, for parsing and creating XML documents
-
-use strict;
-use warnings;
-use Carp;
-use Scalar::Util qw( weaken );
-require Exporter;
-our @ISA = qw(Exporter);
-our @EXPORT_OK = qw(tidy_xml object_to_xml xml_to_object simple_to_xml xml_to_simple check_xml xml_escape);
-our %EXPORT_TAGS = (all => [@EXPORT_OK]);
-use Encode;
-
-
-sub _encode {
-	my $string = shift;
-	my $entities = shift || {};
-	defined $string or $string = '';
-	my %replace = 	(
-					'<' => '&lt;',
-					'>' => '&gt;',
-					'&' => '&amp;',
-					'\'' => '&apos;',
-					'"' => '&quot;',
-					);
-	my $keys = "(".join("|", sort {length($b) <=> length($a)} keys %replace).")";
-	$string =~ s/$keys/$replace{$1}/g;
-	return $string;
-}
-
-
-sub xml_escape {
-	my ($string) = @_;
-
-	return _encode($string);
-}
-
-sub _decode {
-	my $string = shift;
-	my $entities = shift || {};
-	my $flags = shift || {};
-	defined $string or $string = '';
-	my %replace = reverse (
-					(reverse (%$entities)),
-					'<' => '&lt;',
-					'>' => '&gt;',
-					'&' => '&amp;',
-					'\'' => '&apos;',
-					'"' => '&quot;',
-	);
-	$string =~ s/\&\#x([0-9a-f]+)\;/chr(hex($1))/egi;
-	$string =~ s/\&\#([0-9]+)\;/chr($1)/eg;
-	my $keys = "(".join("|", keys %replace).")";
-	$string =~ s/$keys/$replace{$1}/g;
-	return $string;
-}
-
-sub _strip {
-	my $string = shift;
-
-	# NOTE: Replace this with the 'r' flag of the substitution operator
-	return defined $string ? ($string =~ /^\s*(.*?)\s*$/s)[0] : $string;
-}
-
-sub _strip_ns {
-	my $string = shift;
-
-	# NOTE: Replace this with the 'r' flag of the substitution operator
-	return defined $string ? ($string =~ /^(?:.+\:)?(.*)$/s)[0] : $string;
-}
-
-
-
-sub tidy_xml {
-	my $xml = shift;
-	my $flags = shift || {};
-
-	my $object = xml_to_object($xml, $flags);
-	defined $object or return $object;
-	_tidy_object($object, undef, $flags);
-	my $return = $object->to_xml({ %$flags, tidy => 0 }) . "\n";
-	return $return;
-}
-
-
-
-sub xml_to_object {
-	my $xml = shift;
-	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
-
-	if ($flags->{'file'}) {
-		open my $fh, '<', $xml	or confess "Error: The file '$xml' could not be opened for reading: $!";
-		$xml = join '', <$fh>;
-		close $fh;
-	}
-
-	my (undef, undef, $encoding) = $xml =~ /<\?xml(\s[^>]+)?\sencoding=(['"])(.*?)\2/g;
-	$encoding = 'UTF-8'		if ! defined $encoding;
-	if ($encoding =~ /^utf-?8$/i) { $encoding = 'UTF-8'; }
-	eval {
-		$xml = decode($encoding, $xml, Encode::FB_CROAK);
-	};
-	! $@	or confess 'Error: Input string is invalid UTF-8';
-
-	my $entities = {};
-
-	# Parse CDATA sections
-	$xml =~ s/<\!\[CDATA\[(.*?)\]\]>/_encode($1)/egs;
-	my @els = $xml =~ /(<!--.*?(?:-->|$)|<[^>]*?>|[^<>]+)/sg;
-	# Remove comments, special markup and initial whitespace
-	{
-		my $init_ws = 1;
-		foreach my $el (@els) {
-			if ($el =~ /^<!--/) {
-				if ($el !~ /-->$/) { confess encode_utf8("Error: unclosed XML comment block - '$el'"); }
-				undef $el;
-			} elsif ($el =~ /^<\?/) { # like <?xml?> or <?target?>
-				if ($el !~ /\?>$/) { confess encode_utf8("Error: Erroneous special markup - '$el'"); }
-				undef $el;
-			} elsif (my ($entname, undef, $entvalue) = $el =~ /^<!ENTITY\s+(\S+)\s+(['"])(.*?)\2\s*>$/g) {
-				$entities->{"&$entname;"} = _decode($entvalue);
-				undef $el;
-			} elsif ($el =~ /<!/) { # like <!DOCTYPE> or <!ELEMENT> or <!ATTLIST>
-				undef $el;
-			} elsif ($init_ws) {
-				if ($el =~ /\S/) {
-					$init_ws = 0;
-				} else {
-					undef $el;
-				}
-			}
-		}
-		@els = grep { defined $_ } @els;
-		if (! @els) { confess "Error: No elements in XML document"; }
-	}
-	my @stack;
-	my $object = bless ({ content => [] }, 'XML::MyXML::II::Object');
-	my $pointer = $object;
-	foreach my $el (@els) {
-		if ($el =~ /^<\/?>$/) {
-			confess encode_utf8("Error: Strange element: '$el'");
-		} elsif ($el =~ /^<\/[^\s>]+>$/) {
-			my ($element) = $el =~ /^<\/(\S+)>$/g;
-			if (! length($element)) { confess encode_utf8("Error: Strange element: '$el'"); }
-			if ($stack[-1]{'element'} ne $element) { confess encode_utf8("Error: Incompatible stack element: stack='".$stack[-1]{'element'}."' element='$el'"); }
-			my $stackentry = pop @stack;
-			if ($#{$stackentry->{'content'}} == -1) {
-				delete $stackentry->{'content'};
-			}
-			$pointer = $stackentry->{'parent'};
-		} elsif ($el =~ /^<[^>]+\/>$/) {
-			my ($element) = $el =~ /^<([^\s>\/]+)/g;
-			if (! length($element)) { confess encode_utf8("Error: Strange element: '$el'"); }
-			my $elementmeta = quotemeta($element);
-			$el =~ s/^<$elementmeta//;
-			$el =~ s/\/>$//;
-			my @attrs = $el =~ /\s+(\S+=(['"]).*?\2)/g;
-			my $i = 1;
-			@attrs = grep {$i++ % 2} @attrs;
-			my %attr;
-			foreach my $attr (@attrs) {
-				my ($name, undef, $value) = $attr =~ /^(\S+?)=(['"])(.*?)\2$/g;
-				if (! length($name) or ! defined($value)) { confess encode_utf8("Error: Strange attribute: '$attr'"); }
-				$attr{$name} = _decode($value, $entities);
-			}
-			my $entry = { element => $element, attrs => \%attr, parent => $pointer };
-			weaken( $entry->{'parent'} );
-			bless $entry, 'XML::MyXML::II::Object';
-			push @{$pointer->{'content'}}, $entry;
-		} elsif ($el =~ /^<[^\s>\/][^>]*>$/) {
-			my ($element) = $el =~ /^<([^\s>]+)/g;
-			if (! length($element)) { confess encode_utf8("Error: Strange element: '$el'"); }
-			my $elementmeta = quotemeta($element);
-			$el =~ s/^<$elementmeta//;
-			$el =~ s/>$//;
-			my @attrs = $el =~ /\s+(\S+=(['"]).*?\2)/g;
-			my $i = 1;
-			@attrs = grep {$i++ % 2} @attrs;
-			my %attr;
-			foreach my $attr (@attrs) {
-				my ($name, undef, $value) = $attr =~ /^(\S+?)=(['"])(.*?)\2$/g;
-				if (! length($name) or ! defined($value)) { confess encode_utf8("Error: Strange attribute: '$attr'"); }
-				$attr{$name} = _decode($value, $entities);
-			}
-			my $entry = { element => $element, attrs => \%attr, content => [], parent => $pointer };
-			weaken( $entry->{'parent'} );
-			bless $entry, 'XML::MyXML::II::Object';
-			push @stack, $entry;
-			push @{$pointer->{'content'}}, $entry;
-			$pointer = $entry;
-		} elsif ($el =~ /^[^<>]*$/) {
-			my $entry = { value => _decode($el, $entities), parent => $pointer };
-			weaken( $entry->{'parent'} );
-			bless $entry, 'XML::MyXML::II::Object';
-			push @{$pointer->{'content'}}, $entry;
-		} else {
-			confess encode_utf8("Error: Strange element: '$el'");
-		}
-	}
-	if (@stack) { confess encode_utf8("Error: The <$stack[-1]{'element'}> element has not been closed in XML"); }
-	$object = $object->{'content'}[0];
-	$object->{'parent'} = undef;
-	return $object;
-}
-
-sub _objectarray_to_xml {
-	my $object = shift;
-
-	my $xml = '';
-	foreach my $stuff (@$object) {
-		if (! defined $stuff->{'element'} and defined $stuff->{'value'}) {
-			$xml .= _encode($stuff->{'value'});
-		} else {
-			$xml .= "<".$stuff->{'element'};
-			foreach my $attrname (keys %{$stuff->{'attrs'}}) {
-				$xml .= " ".$attrname.'="'._encode($stuff->{'attrs'}{$attrname}).'"';
-			}
-			if (! defined $stuff->{'content'}) {
-				$xml .= "/>"
-			} else {
-				$xml .= ">";
-				$xml .= _objectarray_to_xml($stuff->{'content'});
-				$xml .= "</".$stuff->{'element'}.">";
-			}
-		}
-	}
-	return $xml;
-}
-
-
-sub object_to_xml {
-	my $object = shift;
-	my $flags = shift || {};
-
-	return $object->to_xml( $flags );
-}
-
-sub _tidy_object {
-	my $object = shift;
-	my $tabs = shift || 0;
-	my $flags = shift || {};
-
-	$flags->{'indentstring'} = "\t" unless exists $flags->{'indentstring'};
-
-	if (! defined $object->{'content'} or ! @{$object->{'content'}}) { return; }
-	my $hastext;
-	my @children = @{$object->{'content'}};
-	foreach my $i (0..$#children) {
-		my $child = $children[$i];
-		if (defined $child->{'value'}) {
-			if ($child->{'value'} =~ /\S/) {
-				$hastext = 1;
-				last;
-			}
-		}
-	}
-	if ($hastext) { return; }
-
-	@{$object->{'content'}} = grep { ! defined $_->{'value'} or $_->{'value'} !~ /^\s*$/ } @{$object->{'content'}};
-
-	@children = @{$object->{'content'}};
-	$object->{'content'} = [];
-	for my $i (0..$#children) {
-		my $whitespace = bless ({ value => "\n".($flags->{'indentstring'}x($tabs+1)), parent => $object }, 'XML::MyXML::II::Object');
-		weaken( $whitespace->{'parent'} );
-		push @{$object->{'content'}}, $whitespace;
-		push @{$object->{'content'}}, $children[$i];
-	}
-	my $whitespace = bless ({ value => "\n".($flags->{'indentstring'}x($tabs)), parent => $object }, 'XML::MyXML::II::Object');
-	weaken( $whitespace->{'parent'} );
-	push @{$object->{'content'}}, $whitespace;
-
-	for my $i (0..$#{$object->{'content'}}) {
-		_tidy_object($object->{'content'}[$i], $tabs+1, $flags);
-	}
-}
-
-
-
-sub simple_to_xml {
-	my $arref = shift;
-	my $flags = shift || {};
-
-	my $xml = '';
-	my ($key, $value, @residue) = (ref $arref eq 'HASH') ? %$arref : @$arref;
-	if (@residue) { confess "Error: the provided simple ref contains more than 1 top element"; }
-	my ($tag) = $key =~ /^(\S+)/g;
-	confess encode_utf8("Error: Strange key: $key") if ! defined $tag;
-
-	if (! ref $value) {
-		if (defined $value and length $value) {
-			$xml .= "<$key>"._encode($value)."</$tag>";
-		} else {
-			$xml .= "<$key/>";
-		}
-	} else {
-		$xml .= "<$key>"._arrayref_to_xml($value, $flags)."</$tag>";
-	}
-	if ($flags->{'tidy'}) { $xml = tidy_xml($xml, { $flags->{'indentstring'} ? (indentstring => $flags->{'indentstring'}) : () }); }
-	my $decl = $flags->{'complete'} ? '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'."\n" : '';
-	$decl .= "<?xml-stylesheet type=\"text/xsl\" href=\"$flags->{'xslt'}\"?>\n" if $flags->{'xslt'};
-	$xml = $decl . $xml;
-
-	if (defined $flags->{'save'}) {
-		open my $fh, '>', $flags->{'save'} or confess "Error: Couldn't open file '$flags->{'save'}' for writing: $!";
-		binmode $fh, ':encoding(UTF-8)';
-		print $fh $xml;
-		close $fh;
-	}
-
-	return encode_utf8( $xml );
-}
-
-
-sub _arrayref_to_xml {
-	my $arref = shift;
-	my $flags = shift || {};
-
-	my $xml = '';
-
-	if (ref $arref eq 'HASH') { return _hashref_to_xml($arref, $flags); }
-
-	foreach (my $i = 0; $i <= $#$arref; ) {
-	#while (@$arref) {
-		my $key = $arref->[$i++];
-		#my $key = shift @$arref;
-		my ($tag) = $key =~ /^(\S+)/g;
-		confess encode_utf8("Error: Strange key: $key") if ! defined $tag;
-		my $value = $arref->[$i++];
-		#my $value = shift @$arref;
-
-		if ($key eq '!as_is') {
-			$xml .= $value if check_xml($value);
-		} elsif (! ref $value) {
-			if (defined $value and length $value) {
-				$xml .= "<$key>"._encode($value)."</$tag>";
-			} else {
-				$xml .= "<$key/>";
-			}
-		} else {
-			$xml .= "<$key>"._arrayref_to_xml($value, $flags)."</$tag>";
-		}
-	}
-	return $xml;
-}
-
-
-sub _hashref_to_xml {
-	my $hashref = shift;
-	my $flags = shift || {};
-
-	my $xml = '';
-
-	while (my ($key, $value) = each %$hashref) {
-		my ($tag) = $key =~ /^(\S+)/g;
-		confess encode_utf8("Error: Strange key: $key") if ! defined $tag;
-
-		if ($key eq '!as_is') {
-			$xml .= $value if check_xml($value);
-		} elsif (! ref $value) {
-			if (defined $value and length $value) {
-				$xml .= "<$key>"._encode($value)."</$tag>";
-			} else {
-				$xml .= "<$key/>";
-			}
-		} else {
-			$xml .= "<$key>"._arrayref_to_xml($value, $flags)."</$tag>";
-		}
-	}
-	return $xml;
-}
-
-
-sub xml_to_simple {
-	my $xml = shift;
-	my $flags = shift || {};
-
-	my $object = xml_to_object($xml, $flags);
-
-	my $return = defined $object ? $object->simplify($flags) : $object;
-
-	return $return;
-}
-
-sub _objectarray_to_simple {
-	my $object = shift;
-	my $flags = shift || {};
-
-	if (! defined $object) { return undef; }
-
-	if ($flags->{'arrayref'}) {
-		return _objectarray_to_simple_arrayref($object, $flags);
-	} else {
-		return _objectarray_to_simple_hashref($object, $flags);
-	}
-}
-
-sub _objectarray_to_simple_hashref {
-	my $object = shift;
-	my $flags = shift || {};
-
-	if (! defined $object) { return undef; }
-
-	my $hashref = {};
-
-	foreach my $stuff (@$object) {
-		if (defined $stuff->{'element'}) {
-			my $key = $stuff->{'element'};
-			if ($flags->{'strip_ns'}) { $key = XML::MyXML::II::_strip_ns($key); }
-			$hashref->{ $key } = _objectarray_to_simple($stuff->{'content'}, $flags);
-		} elsif (defined $stuff->{'value'}) {
-			my $value = $stuff->{'value'};
-			if ($flags->{'strip'}) { $value = XML::MyXML::II::_strip($value); }
-			return $value if $value =~ /\S/;
-		}
-	}
-
-	if (keys %$hashref) {
-		return $hashref;
-	} else {
-		return undef;
-	}
-}
-
-sub _objectarray_to_simple_arrayref {
-	my $object = shift;
-	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
-
-	if (! defined $object) { return undef; }
-
-	my $arrayref = [];
-
-	foreach my $stuff (@$object) {
-		if (defined $stuff->{'element'}) {
-			my $key = $stuff->{'element'};
-			if ($flags->{'strip_ns'}) { $key = XML::MyXML::II::_strip_ns($key); }
-			push @$arrayref, ( $key, _objectarray_to_simple($stuff->{'content'}, $flags) );
-			#$hashref->{ $key } = _objectarray_to_simple($stuff->{'content'}, $flags);
-		} elsif (defined $stuff->{'value'}) {
-			my $value = $stuff->{'value'};
-			if ($flags->{'strip'}) { $value = XML::MyXML::II::_strip($value); }
-			return $value if $value =~ /\S/;
-		}
-	}
-
-	if (@$arrayref) {
-		return $arrayref;
-	} else {
-		return undef;
-	}
-}
-
-
-
-sub check_xml {
-	my $xml = shift;
-	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
-
-	my $obj = eval { xml_to_object($xml, $flags) };
-	return ! $@;
-}
-
-
-
-package XML::MyXML::II::Object;
-{
-  $XML::MyXML::II::Object::VERSION = '0.1002';
-}
-
-use Carp;
-use Encode;
-
-
-sub new {
-	my $class = shift;
-	my $xml = shift;
-
-	my $obj = XML::MyXML::II::xml_to_object($xml);
-	bless $obj, $class;
-	return $obj;
-}
-
-sub _parse_description {
-	my ($desc) = @_;
-
-	my ($tag, $attrs_str) = $desc =~ /^([^\[]*)(.*)$/g;
-	my %attrs = $attrs_str =~ /\[([^=\]]+)(?:=([^\]]*))?\]/g;
-
-	return ($tag, \%attrs);
-}
-
-sub cmp_element {
-	my ($self, $desc) = @_;
-
-	my ($tag, $attrs) = ref $desc
-			? @$desc{qw/ tag attrs /}
-			: _parse_description($desc);
-
-	! length $tag or $self->{'element'} =~ /(^|\:)\Q$tag\E$/	or return 0;
-	foreach my $attr (keys %$attrs) {
-		my $val = $self->attr($attr);
-		defined $val											or return 0;
-		! defined $attrs->{$attr} or $attrs->{$attr} eq $val	or return 0;
-	}
-
-	return 1;
-}
-
-sub children {
-	my $self = shift;
-	my $tag = shift;
-
-	$tag = '' if ! defined $tag;
-
-	my @all_children = grep { defined $_->{'element'} } @{$self->{'content'}};
-	length $tag		or return @all_children;
-
-	($tag, my $attrs) = _parse_description($tag);
-	my $desc = { tag => $tag, attrs => $attrs };
-
-	my @results;
-	CHILD: foreach my $child (@all_children) {
-		$child->cmp_element($desc)		or next;
-		push @results, $child;
-	}
-
-	return @results;
-}
-
-sub parent {
-	my $self = shift;
-
-	return $self->{'parent'};
-}
-
-
-sub path {
-	my $self = shift;
-	my $path = shift;
-
-	my @path;
-	my $orig_path = $path;
-	$path = "/" . $path;
-	while (length $path) {
-		my $success = $path =~ s!^/((?:[^/\[]*)?(?:\[[^\]]+\])*)!!;
-		my $seg = $1;
-		if ($success) {
-			push @path, $seg;
-		} else {
-			die "Invalid path: $orig_path";
-		}
-	}
-
-	my $el = $self;
-	for (my $i = 0; $i < $#path; $i++) {
-		my $pathstep = $path[$i];
-		($el) = $el->children($pathstep);
-		if (! defined $el) { return; }
-	}
-	return wantarray ? $el->children($path[$#path]) : ($el->children($path[$#path]))[0];
-}
-
-
-sub value {
-	my $self = shift;
-	my $flags = shift || {};
-
-	if ($self->{'content'} and $self->{'content'}[0]) {
-		my $value = $self->{'content'}[0]{'value'};
-		if ($flags->{'strip'}) { $value = XML::MyXML::II::_strip($value); }
-		return $value;
-	} else {
-		return undef;
-	}
-}
-
-
-sub attr {
-	my $self = shift;
-	my $attrname = shift;
-	my ($set_to, $must_set, $flags);
-	if (@_) {
-		my $next = shift;
-		if (! ref $next) {
-			$set_to = $next;
-			$must_set = 1;
-			$flags = shift;
-		} else {
-			$flags = $next;
-		}
-	}
-	$flags ||= {};
-
-	if (defined $attrname) {
-		if ($must_set) {
-			if (defined ($set_to)) {
-				$self->{'attrs'}{$attrname} = $set_to;
-				return $set_to;
-			} else {
-				delete $self->{'attrs'}{$attrname};
-				return;
-			}
-		} else {
-			my $attrvalue = $self->{'attrs'}->{$attrname};
-			return $attrvalue;
-		}
-	} else {
-		return %{$self->{'attrs'}};
-	}
-}
-
-
-sub tag {
-	my $self = shift;
-	my $flags = shift || {};
-
-	my $tag = $self->{'element'};
-	if (defined $tag) {
-		$tag =~ s/^.*\://	if $flags->{'strip_ns'};
-		return $tag;
-	} else {
-		return undef;
-	}
-}
-
-
-sub simplify {
-	my $self = shift;
-	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
-
-	my $simple = XML::MyXML::II::_objectarray_to_simple([$self], $flags);
-	if (! $flags->{'internal'}) {
-		return $simple;
-	} else {
-		if (ref $simple eq 'HASH') {
-			return (values %$simple)[0];
-		} elsif (ref $simple eq 'ARRAY') {
-			return $simple->[1];
-		}
-	}
-}
-
-
-sub to_xml {
-	my $self = shift;
-	my $flags = shift || {};
-
-	my $decl = $flags->{'complete'} ? '<?xml version="1.1" encoding="UTF-8" standalone="yes" ?>'."\n" : '';
-	my $xml = encode_utf8( XML::MyXML::II::_objectarray_to_xml([$self]) );
-	if ($flags->{'tidy'}) { $xml = XML::MyXML::II::tidy_xml($xml, { %$flags, complete => 0, save => undef }); }
-	$xml = $decl . $xml;
-	if (defined $flags->{'save'}) {
-		open my $fh, '>', $flags->{'save'} or confess "Error: Couldn't open file '$flags->{'save'}' for writing: $!";
-		print $fh $xml;
-		close $fh;
-	}
-	return $xml;
-}
-
-
-sub to_tidy_xml {
-	my $self = shift;
-	my $flags = shift || {};
-
-	$flags->{'tidy'} = 1;
-	return $self->to_xml( $flags );
-}
-
-
-
-
-
-1; # End of XML::MyXML::II
-
-__END__
-
-=pod
-
-=head1 NAME
-
-XML::MyXML::II - A simple-to-use XML module, for parsing and creating XML documents
-
-=head1 VERSION
-
-version 0.1002
-
-=head1 SYNOPSIS
-
-    use XML::MyXML::II qw(tidy_xml xml_to_object);
-    use XML::MyXML::II qw(:all);
-
-    my $xml = "<item><name>Table</name><price><usd>10.00</usd><eur>8.50</eur></price></item>";
-    print tidy_xml($xml);
-
-    my $obj = xml_to_object($xml);
-    print "Price in Euros = " . $obj->path('price/eur')->value;
-
-    $obj->simplify is hashref { item => { name => 'Table', price => { usd => '10.00', eur => '8.50' } } }
-    $obj->simplify({ internal => 1 }) is hashref { name => 'Table', price => { usd => '10.00', eur => '8.50' } }
-
-=head1 EXPORT
-
-tidy_xml, xml_to_object, object_to_xml, simple_to_xml, xml_to_simple, check_xml
-
-=head1 DIFFERENCES FROM XML::MyXML
-
-XML::MyXML::II is similar to L<XML::MyXML>, but introduced some changes in v0.100 that broke backwards compatibility with programs that use XML::MyXML. For this reason, XML::MyXML has been kept in its place, but will not be maintained anymore. XML::MyXML::II is the module you should use (and will be maintained). Its differences from the older L<XML::MyXML> are the following:
-
-=over
-
-=item * Better handling of unicode: Only XML documents (both parameters and returned values) are in bytes/octets. All other strings contain characters rather than bytes/octets (see section L</"FEATURES & LIMITATIONS">). Removed the C<utf8> option from the functions & methods that used it.
-
-=item * Objects created by this module will now be automatically destroyed once out of scope (because I replaced cycles with weakened refs)
-
-=item * Removed the pretty useless C<soft> option from the functions and methods that used it. If you want XML::MyXML's soft behaviour, you will need to C<eval {}> from your own program.
-
-=item * C<< $obj->tag >> doesn't by default strip the namespace from the returned tagname
-
-=back
-
-=head1 FEATURES & LIMITATIONS
-
-This module can parse XML comments, CDATA sections, XML entities (the standard five and numeric ones) and simple non-recursive C<< <!ENTITY> >>s
-
-It will ignore (won't parse) C<< <!DOCTYPE...> >>, C<< <?...?> >> and other C<< <!...> >> special markup
-
-XML documents passed as parameters to this module's functions must be strings containing bytes/octets, rather than contain characters. They also must be UTF-8 encoded unless an encoding is declared in the initial XML declaration <?xml ... ?> of the document. All XML documents produced by this module will be UTF-8 encoded (bytes/octets). However all other strings which are output by this module's functions and methods (and which are not XML documents) will contain characters rather than bytes/octets.
-
-XML documents to be parsed may not contain the C<< > >> character unencoded in attribute values
-
-=head1 OPTIONAL FUNCTION FLAGS
-
-Some functions and methods in this module accept optional flags, listed under each function in the documentation. They are optional, default to zero unless stated otherwise, and can be used as follows: S<C<< function_name( $param1, { flag1 => 1, flag2 => 1 } ) >>>. This is what each flag does:
-
-C<strip> : the function will strip initial and ending whitespace from all text values returned
-
-C<file> : the function will expect the path to a file containing an XML document to parse, instead of an XML string
-
-C<complete> : the function's XML output will include an XML declaration (C<< <?xml ... ?>  >>) in the beginning
-
-C<internal> : the function will only return the contents of an element in a hashref instead of the element itself (see L</SYNOPSIS> for example)
-
-C<tidy> : the function will return tidy XML
-
-C<indentstring> : when producing tidy XML, this denotes the string with which child elements will be indented (Default is the 'tab' character)
-
-C<save> : the function (apart from doing what it's supposed to do) will also save its XML output in a file whose path is denoted by this flag
-
-C<strip_ns> : strip the namespaces (characters up to and including ':') from the tags
-
-C<xslt> : will add a <?xml-stylesheet?> link in the XML that's being output, of type 'text/xsl', pointing to the filename or URL denoted by this flag
-
-C<arrayref> : the function will create a simple arrayref instead of a simple hashref (which will preserve order and elements with duplicate tags)
-
-=head1 FUNCTIONS
-
-=head2 xml_escape($string)
-
-Returns the same string, but with the C<< < >>, C<< > >>, C<< & >>, C<< " >> and C<< ' >> characters replaced by their XML entities (e.g. C<< &amp; >>).
-
-=head2 tidy_xml($raw_xml)
-
-Returns the XML string in a tidy format (with tabs & newlines)
-
-Optional flags: C<file>, C<complete>, C<indentstring>, C<save>
-
-=head2 xml_to_object($raw_xml)
-
-Creates an 'XML::MyXML::II::Object' object from the raw XML provided
-
-Optional flags: C<file>
-
-=head2 object_to_xml($object)
-
-Creates an XML string from the 'XML::MyXML::II::Object' object provided
-
-Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>
-
-=head2 simple_to_xml($simple_array_ref)
-
-Produces a raw XML string from either an array reference, a hash reference or a mixed structure such as these examples:
-
-    { thing => { name => 'John', location => { city => 'New York', country => 'U.S.A.' } } }
-    [ thing => [ name => 'John', location => [ city => 'New York', country => 'U.S.A.' ] ] ]
-    { thing => { name => 'John', location => [ city => 'New York', city => 'Boston', country => 'U.S.A.' ] } }
-
-All the strings in C<$simple_array_ref> need to contain characters, rather than bytes/octets. The XML output of this function however will be a UTF-8 encoded string (i.e. will contain bytes/octets).
-
-Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>, C<xslt>
-
-=head2 xml_to_simple($raw_xml)
-
-Produces a very simple hash object from the raw XML string provided. An example hash object created thusly is this: S<C<< { thing => { name => 'John', location => { city => 'New York', country => 'U.S.A.' } } } >>>
-
-Since the object created is a hashref, duplicate keys will be discarded. WARNING: This function only works on very simple XML strings, i.e. children of an element may not consist of both text and elements (child elements will be discarded in that case)
-
-All strings contained in the output simple structure, will contain characters rather than octets/bytes.
-
-Optional flags: C<internal>, C<strip>, C<file>, C<strip_ns>, C<arrayref>
-
-=head2 check_xml($raw_xml)
-
-Returns true if the $raw_xml string is valid XML (valid enough to be used by this module), and false otherwise.
-
-Optional flags: C<file>
-
-=head1 OBJECT METHODS
-
-=head2 $obj->path("subtag1/subsubtag2[attr1=val1][attr2]/.../subsubsubtagX")
-
-Returns the element specified by the path as an XML::MyXML::II::Object object. When there are more than one tags with the specified name in the last step of the path, it will return all of them as an array. In scalar context will only return the first one. CSS3-style attribute selectors are allowed in the path next to the tagnames, for example: C<< p[class=big] >> will only return C<< <p> >> elements that contain an attribute called "class" with a value of "big". p[class] on the other hand will return p elements having a "class" attribute, but that attribute can have any value.
-
-=head2 $obj->value
-
-When the element represented by the $obj object has only text contents, returns those contents as a string. If the $obj element has no contents, value will return an empty string.
-
-Optional flags: C<strip>
-
-=head2 $obj->attr('attrname' [, 'attrvalue'])
-
-Gets/Sets the value of the 'attrname' attribute of the top element. Returns undef if attribute does not exist. If called without the 'attrname' paramter, returns a hash with all attribute => value pairs. If setting with an attrvalue of C<undef>, then removes that attribute entirely.
-
-Input parameters and output are all in character strings, rather than octets/bytes.
-
-Optional flags: none
-
-=head2 $obj->tag
-
-Returns the tag of the $obj element. E.g. if $obj represents an <rss:item> element, C<< $obj->tag >> will return the string 'rss:item'.
-Returns undef if $obj doesn't represent a tag.
-
-Optional flags: C<strip_ns>
-
-=head2 $obj->simplify
-
-Returns a very simple hashref, like the one returned with C<&XML::MyXML::II::xml_to_simple>. Same restrictions and warnings apply.
-
-Optional flags: C<internal>, C<strip>, C<strip_ns>, C<arrayref>
-
-=head2 $obj->to_xml
-
-Returns the XML string of the object, just like calling C<object_to_xml( $obj )>
-
-Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>
-
-=head2 $obj->to_tidy_xml
-
-Returns the XML string of the object in tidy form, just like calling C<tidy_xml( object_to_xml( $obj ) )>
-
-Optional flags: C<complete>, C<indentstring>, C<save>
-
-=head1 BUGS
-
-If you have a Github account, report your issues at
-L<https://github.com/akarelas/xml-myxml/issues>.
-I will be notified, and then you'll automatically be notified of progress on
-your bug as I make changes.
-
-=head1 AUTHOR
-
-Alexander Karelas <karjala@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is copyright (c) 2013 by Alexander Karelas.
-
-This is free software; you can redistribute it and/or modify it under
-the same terms as the Perl 5 programming language system itself.
-
-=cut
@@ -1,13 +1,10 @@
 package XML::MyXML;
-{
-  $XML::MyXML::VERSION = '0.1002';
-}
 # ABSTRACT: A simple-to-use XML module, for parsing and creating XML documents
-
+$XML::MyXML::VERSION = '0.9007';
 use strict;
 use warnings;
-use utf8;
 use Carp;
+use Scalar::Util qw( weaken );
 require Exporter;
 our @ISA = qw(Exporter);
 our @EXPORT_OK = qw(tidy_xml object_to_xml xml_to_object simple_to_xml xml_to_simple check_xml xml_escape);
@@ -43,34 +40,45 @@ sub _decode {
 	my $entities = shift || {};
 	my $flags = shift || {};
 	defined $string or $string = '';
-	my %replace = reverse (
-					(reverse (%$entities)),
+	my %replace = ( %$entities, reverse(
 					'<' => '&lt;',
 					'>' => '&gt;',
 					'&' => '&amp;',
 					'\'' => '&apos;',
 					'"' => '&quot;',
-	);
-	Encode::_utf8_on($string);
-	if (utf8::valid($string)) {
-		$string =~ s/\&\#x([0-9a-f]+)\;/chr(hex($1))/egi;
-		$string =~ s/\&\#([0-9]+)\;/chr($1)/eg;
+	));
+	my @capture = map "\Q$_\E", keys %replace;
+	push @capture, '&#x[0-9A-Fa-f]+;', '&#[0-9]+;';
+	my $capture = "(".join("|", @capture).")";
+	my @captured = $string =~ /$capture/g;
+	@captured	or return $string;
+	my %conv;
+	foreach my $e (@captured) {
+		if (exists $conv{$e}) { next; }
+		if (exists $replace{$e}) {
+			$conv{$e} = $replace{$e};
+		} elsif ($e =~ /^&#x([0-9a-fA-F]+);$/) {
+			$conv{$e} = chr(hex($1));
+		} elsif ($e =~ /^&#([0-9]+);$/) {
+			$conv{$e} = chr($1);
+		}
 	}
-	Encode::_utf8_off($string);
-	my $keys = "(".join("|", keys %replace).")";
-	$string =~ s/$keys/$replace{$1}/g;
+	my $keys = "(".join("|", map "\Q$_\E", keys %conv).")";
+	$string =~ s/$keys/$conv{$1}/g;
 	return $string;
 }
 
 sub _strip {
 	my $string = shift;
 
+	# NOTE: Replace this with the 'r' flag of the substitution operator
 	return defined $string ? ($string =~ /^\s*(.*?)\s*$/s)[0] : $string;
 }
 
 sub _strip_ns {
 	my $string = shift;
 
+	# NOTE: Replace this with the 'r' flag of the substitution operator
 	return defined $string ? ($string =~ /^(?:.+\:)?(.*)$/s)[0] : $string;
 }
 
@@ -78,14 +86,12 @@ sub _strip_ns {
 
 sub tidy_xml {
 	my $xml = shift;
-	if ($xml eq 'XML::MyXML') { confess "Error: 'tidy_xml' is a function, not a method"; }
 	my $flags = shift || {};
 
 	my $object = xml_to_object($xml, $flags);
 	defined $object or return $object;
 	_tidy_object($object, undef, $flags);
 	my $return = $object->to_xml({ %$flags, tidy => 0 }) . "\n";
-	$object->delete();
 	return $return;
 }
 
@@ -95,25 +101,19 @@ sub xml_to_object {
 	my $xml = shift;
 	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
 
-	my $soft = $flags->{'soft'}; # soft = 'don't die if can't parse, just return undef'
-
 	if ($flags->{'file'}) {
-		open my $fh, '<', $xml or do { confess "Error: The file '$xml' could not be opened for reading: $!" unless $soft; return undef; };
+		open my $fh, '<', $xml	or croak "Error: The file '$xml' could not be opened for reading: $!";
 		$xml = join '', <$fh>;
 		close $fh;
 	}
 
 	my (undef, undef, $encoding) = $xml =~ /<\?xml(\s[^>]+)?\sencoding=(['"])(.*?)\2/g;
-	Encode::_utf8_on($xml);
-	if (! utf8::valid($xml)) {
-		if ($encoding and $encoding !~ /^utf-?8$/i) {
-			Encode::_utf8_off($xml);
-			$xml = decode($encoding, $xml);
-			Encode::_utf8_on($xml);
-		}
-	}
-	if (! utf8::valid($xml)) { confess "Error: Input string is invalid UTF-8" unless $soft; return undef; }
-	Encode::_utf8_off($xml);
+	$encoding = 'UTF-8'		if ! defined $encoding;
+	if ($encoding =~ /^utf-?8$/i) { $encoding = 'UTF-8'; }
+	eval {
+		$xml = decode($encoding, $xml, Encode::FB_CROAK);
+	};
+	! $@	or croak 'Error: Input string is invalid UTF-8';
 
 	my $entities = {};
 
@@ -125,10 +125,10 @@ sub xml_to_object {
 		my $init_ws = 1;
 		foreach my $el (@els) {
 			if ($el =~ /^<!--/) {
-				if ($el !~ /-->$/) { confess "Error: unclosed XML comment block - '$el'" unless $soft; return undef; }
+				if ($el !~ /-->$/) { croak encode_utf8("Error: unclosed XML comment block - '$el'"); }
 				undef $el;
 			} elsif ($el =~ /^<\?/) { # like <?xml?> or <?target?>
-				if ($el !~ /\?>$/) { confess "Error: Erroneous special markup - '$el'" unless $soft; return undef; }
+				if ($el !~ /\?>$/) { croak encode_utf8("Error: Erroneous special markup - '$el'"); }
 				undef $el;
 			} elsif (my ($entname, undef, $entvalue) = $el =~ /^<!ENTITY\s+(\S+)\s+(['"])(.*?)\2\s*>$/g) {
 				$entities->{"&$entname;"} = _decode($entvalue);
@@ -144,18 +144,18 @@ sub xml_to_object {
 			}
 		}
 		@els = grep { defined $_ } @els;
-		if (! @els) { confess "Error: No elements in XML document" unless $soft; return undef; }
+		if (! @els) { croak "Error: No elements in XML document"; }
 	}
 	my @stack;
 	my $object = bless ({ content => [] }, 'XML::MyXML::Object');
 	my $pointer = $object;
 	foreach my $el (@els) {
 		if ($el =~ /^<\/?>$/) {
-			confess "Error: Strange element: '$el'" unless $soft; $object->delete(); return undef;
+			croak encode_utf8("Error: Strange element: '$el'");
 		} elsif ($el =~ /^<\/[^\s>]+>$/) {
 			my ($element) = $el =~ /^<\/(\S+)>$/g;
-			if (! length($element)) { confess "Error: Strange element: '$el'" unless $soft; $object->delete(); return undef; }
-			if ($stack[$#stack]->{'element'} ne $element) { confess "Error: Incompatible stack element: stack='".$stack[$#stack]->{'element'}."' element='$el'" unless $soft; $object->delete(); return undef; }
+			if (! length($element)) { croak encode_utf8("Error: Strange element: '$el'"); }
+			if ($stack[-1]{'element'} ne $element) { croak encode_utf8("Error: Incompatible stack element: stack='".$stack[-1]{'element'}."' element='$el'"); }
 			my $stackentry = pop @stack;
 			if ($#{$stackentry->{'content'}} == -1) {
 				delete $stackentry->{'content'};
@@ -163,7 +163,7 @@ sub xml_to_object {
 			$pointer = $stackentry->{'parent'};
 		} elsif ($el =~ /^<[^>]+\/>$/) {
 			my ($element) = $el =~ /^<([^\s>\/]+)/g;
-			if (! length($element)) { confess "Error: Strange element: '$el'" unless $soft; $object->delete(); return undef; }
+			if (! length($element)) { croak encode_utf8("Error: Strange element: '$el'"); }
 			my $elementmeta = quotemeta($element);
 			$el =~ s/^<$elementmeta//;
 			$el =~ s/\/>$//;
@@ -173,15 +173,16 @@ sub xml_to_object {
 			my %attr;
 			foreach my $attr (@attrs) {
 				my ($name, undef, $value) = $attr =~ /^(\S+?)=(['"])(.*?)\2$/g;
-				if (! length($name) or ! defined($value)) { confess "Error: Strange attribute: '$attr'" unless $soft; $object->delete(); return undef; }
+				if (! length($name) or ! defined($value)) { croak encode_utf8("Error: Strange attribute: '$attr'"); }
 				$attr{$name} = _decode($value, $entities);
 			}
 			my $entry = { element => $element, attrs => \%attr, parent => $pointer };
+			weaken( $entry->{'parent'} );
 			bless $entry, 'XML::MyXML::Object';
 			push @{$pointer->{'content'}}, $entry;
 		} elsif ($el =~ /^<[^\s>\/][^>]*>$/) {
 			my ($element) = $el =~ /^<([^\s>]+)/g;
-			if (! length($element)) { confess "Error: Strange element: '$el'" unless $soft; $object->delete(); return undef; }
+			if (! length($element)) { croak encode_utf8("Error: Strange element: '$el'"); }
 			my $elementmeta = quotemeta($element);
 			$el =~ s/^<$elementmeta//;
 			$el =~ s/>$//;
@@ -191,23 +192,25 @@ sub xml_to_object {
 			my %attr;
 			foreach my $attr (@attrs) {
 				my ($name, undef, $value) = $attr =~ /^(\S+?)=(['"])(.*?)\2$/g;
-				if (! length($name) or ! defined($value)) { confess "Error: Strange attribute: '$attr'" unless $soft; $object->delete(); return undef; }
+				if (! length($name) or ! defined($value)) { croak encode_utf8("Error: Strange attribute: '$attr'"); }
 				$attr{$name} = _decode($value, $entities);
 			}
 			my $entry = { element => $element, attrs => \%attr, content => [], parent => $pointer };
+			weaken( $entry->{'parent'} );
 			bless $entry, 'XML::MyXML::Object';
 			push @stack, $entry;
 			push @{$pointer->{'content'}}, $entry;
 			$pointer = $entry;
 		} elsif ($el =~ /^[^<>]*$/) {
 			my $entry = { value => _decode($el, $entities), parent => $pointer };
+			weaken( $entry->{'parent'} );
 			bless $entry, 'XML::MyXML::Object';
 			push @{$pointer->{'content'}}, $entry;
 		} else {
-			confess "Error: Strange element: '$el'" unless $soft; $object->delete(); return undef;
+			croak encode_utf8("Error: Strange element: '$el'");
 		}
 	}
-	if (@stack) { confess "Error: The <$stack[-1]->{'element'}> element has not been closed in XML" unless $soft; $object->delete(); return undef; }
+	if (@stack) { croak encode_utf8("Error: The <$stack[-1]{'element'}> element has not been closed in XML"); }
 	$object = $object->{'content'}[0];
 	$object->{'parent'} = undef;
 	return $object;
@@ -271,10 +274,14 @@ sub _tidy_object {
 	@children = @{$object->{'content'}};
 	$object->{'content'} = [];
 	for my $i (0..$#children) {
-		push @{$object->{'content'}}, bless ({ value => "\n".($flags->{'indentstring'}x($tabs+1)), parent => $object }, 'XML::MyXML::Object');
+		my $whitespace = bless ({ value => "\n".($flags->{'indentstring'}x($tabs+1)), parent => $object }, 'XML::MyXML::Object');
+		weaken( $whitespace->{'parent'} );
+		push @{$object->{'content'}}, $whitespace;
 		push @{$object->{'content'}}, $children[$i];
 	}
-	push @{$object->{'content'}}, bless ({ value => "\n".($flags->{'indentstring'}x($tabs)), parent => $object }, 'XML::MyXML::Object');
+	my $whitespace = bless ({ value => "\n".($flags->{'indentstring'}x($tabs)), parent => $object }, 'XML::MyXML::Object');
+	weaken( $whitespace->{'parent'} );
+	push @{$object->{'content'}}, $whitespace;
 
 	for my $i (0..$#{$object->{'content'}}) {
 		_tidy_object($object->{'content'}[$i], $tabs+1, $flags);
@@ -289,13 +296,11 @@ sub simple_to_xml {
 
 	my $xml = '';
 	my ($key, $value, @residue) = (ref $arref eq 'HASH') ? %$arref : @$arref;
-	Encode::_utf8_off($key);
-	if (@residue) { confess "Error: the provided simple ref contains more than 1 top element"; }
+	if (@residue) { croak "Error: the provided simple ref contains more than 1 top element"; }
 	my ($tag) = $key =~ /^(\S+)/g;
-	confess "Error: Strange key: $key" if ! defined $tag;
+	croak encode_utf8("Error: Strange key: $key") if ! defined $tag;
 
 	if (! ref $value) {
-		Encode::_utf8_off($value);
 		if (defined $value and length $value) {
 			$xml .= "<$key>"._encode($value)."</$tag>";
 		} else {
@@ -308,16 +313,15 @@ sub simple_to_xml {
 	my $decl = $flags->{'complete'} ? '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'."\n" : '';
 	$decl .= "<?xml-stylesheet type=\"text/xsl\" href=\"$flags->{'xslt'}\"?>\n" if $flags->{'xslt'};
 	$xml = $decl . $xml;
-	if ($flags->{'utf8'}) { Encode::_utf8_on($xml); }
 
 	if (defined $flags->{'save'}) {
-		open my $fh, '>', $flags->{'save'} or confess "Error: Couldn't open file '$flags->{'save'}' for writing: $!";
-		if ($flags->{'utf8'}) { binmode $fh, ':encoding(UTF-8)'; }
+		open my $fh, '>', $flags->{'save'} or croak "Error: Couldn't open file '$flags->{'save'}' for writing: $!";
+		binmode $fh, ':encoding(UTF-8)';
 		print $fh $xml;
 		close $fh;
 	}
 
-	return $xml;
+	return encode_utf8( $xml );
 }
 
 
@@ -332,18 +336,15 @@ sub _arrayref_to_xml {
 	foreach (my $i = 0; $i <= $#$arref; ) {
 	#while (@$arref) {
 		my $key = $arref->[$i++];
-		Encode::_utf8_off($key);
 		#my $key = shift @$arref;
 		my ($tag) = $key =~ /^(\S+)/g;
-		confess "Error: Strange key: $key" if ! defined $tag;
+		croak encode_utf8("Error: Strange key: $key") if ! defined $tag;
 		my $value = $arref->[$i++];
 		#my $value = shift @$arref;
 
 		if ($key eq '!as_is') {
-			Encode::_utf8_off($value);
 			$xml .= $value if check_xml($value);
 		} elsif (! ref $value) {
-			Encode::_utf8_off($value);
 			if (defined $value and length $value) {
 				$xml .= "<$key>"._encode($value)."</$tag>";
 			} else {
@@ -364,15 +365,12 @@ sub _hashref_to_xml {
 	my $xml = '';
 
 	while (my ($key, $value) = each %$hashref) {
-		Encode::_utf8_off($key);
 		my ($tag) = $key =~ /^(\S+)/g;
-		confess "Error: Strange key: $key" if ! defined $tag;
+		croak encode_utf8("Error: Strange key: $key") if ! defined $tag;
 
 		if ($key eq '!as_is') {
-			Encode::_utf8_off($value);
 			$xml .= $value if check_xml($value);
 		} elsif (! ref $value) {
-			Encode::_utf8_off($value);
 			if (defined $value and length $value) {
 				$xml .= "<$key>"._encode($value)."</$tag>";
 			} else {
@@ -394,8 +392,6 @@ sub xml_to_simple {
 
 	my $return = defined $object ? $object->simplify($flags) : $object;
 
-	$object->delete();
-
 	return $return;
 }
 
@@ -423,13 +419,11 @@ sub _objectarray_to_simple_hashref {
 	foreach my $stuff (@$object) {
 		if (defined $stuff->{'element'}) {
 			my $key = $stuff->{'element'};
-			if ($flags->{'strip_ns'}) { $key = XML::MyXML::_strip_ns($key); }
-			Encode::_utf8_on($key) if $flags->{'utf8'};
+			if ($flags->{'strip_ns'}) { $key = _strip_ns($key); }
 			$hashref->{ $key } = _objectarray_to_simple($stuff->{'content'}, $flags);
 		} elsif (defined $stuff->{'value'}) {
 			my $value = $stuff->{'value'};
-			if ($flags->{'strip'}) { $value = XML::MyXML::_strip($value); }
-			Encode::_utf8_on($value) if $flags->{'utf8'};
+			if ($flags->{'strip'}) { $value = _strip($value); }
 			return $value if $value =~ /\S/;
 		}
 	}
@@ -445,8 +439,6 @@ sub _objectarray_to_simple_arrayref {
 	my $object = shift;
 	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
 
-	if (ref $flags ne 'HASH') { confess "Error: This method of setting flags is deprecated in XML::MyXML v0.083 - check module's documentation for the new way"; }
-
 	if (! defined $object) { return undef; }
 
 	my $arrayref = [];
@@ -454,14 +446,12 @@ sub _objectarray_to_simple_arrayref {
 	foreach my $stuff (@$object) {
 		if (defined $stuff->{'element'}) {
 			my $key = $stuff->{'element'};
-			if ($flags->{'strip_ns'}) { $key = XML::MyXML::_strip_ns($key); }
-			Encode::_utf8_on($key) if $flags->{'utf8'};
+			if ($flags->{'strip_ns'}) { $key = _strip_ns($key); }
 			push @$arrayref, ( $key, _objectarray_to_simple($stuff->{'content'}, $flags) );
 			#$hashref->{ $key } = _objectarray_to_simple($stuff->{'content'}, $flags);
 		} elsif (defined $stuff->{'value'}) {
 			my $value = $stuff->{'value'};
-			if ($flags->{'strip'}) { $value = XML::MyXML::_strip($value); }
-			Encode::_utf8_on($value) if $flags->{'utf8'};
+			if ($flags->{'strip'}) { $value = _strip($value); }
 			return $value if $value =~ /\S/;
 		}
 	}
@@ -479,25 +469,16 @@ sub check_xml {
 	my $xml = shift;
 	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
 
-	if (ref $flags ne 'HASH') { confess "Error: This method of setting flags is deprecated in XML::MyXML v0.083 - check module's documentation for the new way"; }
-
-	my $obj = xml_to_object($xml, { %$flags, soft => 1 });
-	if ($obj) {
-		$obj->delete();
-		return 1;
-	} else {
-		return 0;
-	}
+	my $obj = eval { xml_to_object($xml, $flags) };
+	return ! $@;
 }
 
 
 
 package XML::MyXML::Object;
-{
-  $XML::MyXML::Object::VERSION = '0.1002';
-}
-
+$XML::MyXML::Object::VERSION = '0.9007';
 use Carp;
+use Encode;
 
 
 sub new {
@@ -569,24 +550,27 @@ sub path {
 
 	my @path;
 	my $orig_path = $path;
-	$path = "/" . $path;
+	my $start_root = $path =~ m!^/!;
+	$path = "/" . $path		unless $start_root;
 	while (length $path) {
 		my $success = $path =~ s!^/((?:[^/\[]*)?(?:\[[^\]]+\])*)!!;
 		my $seg = $1;
 		if ($success) {
 			push @path, $seg;
 		} else {
-			die "Invalid path: $orig_path";
+			croak "Invalid XML path: $orig_path";
 		}
 	}
 
-	my $el = $self;
-	for (my $i = 0; $i < $#path; $i++) {
-		my $pathstep = $path[$i];
-		($el) = $el->children($pathstep);
-		if (! defined $el) { return; }
+	my @result = ($self);
+	if ($start_root) {
+		$self->cmp_element(shift @path)		or return;
+	}
+	for (my $i = 0; $i <= $#path; $i++) {
+		@result = $result[0]->children( $path[$i] );
+		@result		or return;
 	}
-	return wantarray ? $el->children($path[$#path]) : ($el->children($path[$#path]))[0];
+	return wantarray ? @result : $result[0];
 }
 
 
@@ -597,7 +581,6 @@ sub value {
 	if ($self->{'content'} and $self->{'content'}[0]) {
 		my $value = $self->{'content'}[0]{'value'};
 		if ($flags->{'strip'}) { $value = XML::MyXML::_strip($value); }
-		Encode::_utf8_on($value) if $flags->{'utf8'};
 		return $value;
 	} else {
 		return undef;
@@ -613,7 +596,6 @@ sub attr {
 		my $next = shift;
 		if (! ref $next) {
 			$set_to = $next;
-			Encode::_utf8_off($set_to);
 			$must_set = 1;
 			$flags = shift;
 		} else {
@@ -626,7 +608,6 @@ sub attr {
 		if ($must_set) {
 			if (defined ($set_to)) {
 				$self->{'attrs'}{$attrname} = $set_to;
-				Encode::_utf8_on($set_to) if $flags->{'utf8'};
 				return $set_to;
 			} else {
 				delete $self->{'attrs'}{$attrname};
@@ -634,17 +615,10 @@ sub attr {
 			}
 		} else {
 			my $attrvalue = $self->{'attrs'}->{$attrname};
-			Encode::_utf8_on($attrvalue) if $flags->{'utf8'};
 			return $attrvalue;
 		}
 	} else {
-		my %attr = %{$self->{'attrs'}};
-		if ($flags->{'utf8'}) {
-			foreach my $key (keys %attr) {
-				Encode::_utf8_on($attr{$key});
-			}
-		}
-		return %attr;
+		return %{$self->{'attrs'}};
 	}
 }
 
@@ -655,8 +629,7 @@ sub tag {
 
 	my $tag = $self->{'element'};
 	if (defined $tag) {
-		$tag =~ s/^.*\://	unless exists $flags->{'strip_ns'} and ! $flags->{'strip_ns'};
-		Encode::_utf8_on($tag) if $flags->{'utf8'};
+		$tag =~ s/^.*\://	if $flags->{'strip_ns'};
 		return $tag;
 	} else {
 		return undef;
@@ -668,8 +641,6 @@ sub simplify {
 	my $self = shift;
 	my $flags = (@_ and defined $_[0]) ? $_[0] : {};
 
-	if (ref $flags ne 'HASH') { confess "Error: This method of setting flags is deprecated in XML::MyXML v0.083 - check module's documentation for the new way"; }
-
 	my $simple = XML::MyXML::_objectarray_to_simple([$self], $flags);
 	if (! $flags->{'internal'}) {
 		return $simple;
@@ -688,13 +659,11 @@ sub to_xml {
 	my $flags = shift || {};
 
 	my $decl = $flags->{'complete'} ? '<?xml version="1.1" encoding="UTF-8" standalone="yes" ?>'."\n" : '';
-	my $xml = XML::MyXML::_objectarray_to_xml([$self]);
+	my $xml = encode_utf8( XML::MyXML::_objectarray_to_xml([$self]) );
 	if ($flags->{'tidy'}) { $xml = XML::MyXML::tidy_xml($xml, { %$flags, complete => 0, save => undef }); }
 	$xml = $decl . $xml;
-	if ($flags->{'utf8'}) { Encode::_utf8_on($xml); }
 	if (defined $flags->{'save'}) {
-		open my $fh, '>', $flags->{'save'} or confess "Error: Couldn't open file '$flags->{'save'}' for writing: $!";
-		if ($flags->{'utf8'}) { binmode $fh, ':encoding(UTF-8)'; }
+		open my $fh, '>', $flags->{'save'} or croak "Error: Couldn't open file '$flags->{'save'}' for writing: $!";
 		print $fh $xml;
 		close $fh;
 	}
@@ -714,46 +683,21 @@ sub to_tidy_xml {
 
 
 
-sub delete {
-	my $self = shift;
-
-	# Remove self from parent's "content" field
-	my $parent = $self->{'parent'};
-	if ($parent) {
-		my $content = $parent->{'content'};
-		if ($content) {
-			my @new = ();
-			foreach my $item (@$content) {
-				if ($item != $self) { push @new, $item; }
-			}
-			$parent->{'content'} = \@new;
-		}
-	}
-
-	my $content = $self->{'content'};
-	if ($content) {
-		foreach my $item (@$content) {
-			$item->delete();
-		}
-	}
-
-	delete $self->{$_} foreach keys %$self;
-}
-
-
 1; # End of XML::MyXML
 
 __END__
 
 =pod
 
+=encoding UTF-8
+
 =head1 NAME
 
 XML::MyXML - A simple-to-use XML module, for parsing and creating XML documents
 
 =head1 VERSION
 
-version 0.1002
+version 0.9007
 
 =head1 SYNOPSIS
 
@@ -769,15 +713,9 @@ version 0.1002
     $obj->simplify is hashref { item => { name => 'Table', price => { usd => '10.00', eur => '8.50' } } }
     $obj->simplify({ internal => 1 }) is hashref { name => 'Table', price => { usd => '10.00', eur => '8.50' } }
 
-=head1 PLEASE USE XML::MyXML::II INSTEAD
-
-B<< *** This module will not be maintained anymore *** Please use L<XML::MyXML::II> instead, which is also contained in this distribution *** >>
-
-It's main improvements are: better unicode handling and automatic object destruction
-
-=head1 EXPORT
+=head1 EXPORTABLE
 
-tidy_xml, xml_to_object, object_to_xml, simple_to_xml, xml_to_simple, check_xml
+xml_escape, tidy_xml, xml_to_object, object_to_xml, simple_to_xml, xml_to_simple, check_xml
 
 =head1 FEATURES & LIMITATIONS
 
@@ -785,7 +723,7 @@ This module can parse XML comments, CDATA sections, XML entities (the standard f
 
 It will ignore (won't parse) C<< <!DOCTYPE...> >>, C<< <?...?> >> and other C<< <!...> >> special markup
 
-Parsed documents must be UTF-8 encoded unless an encoding is declared in the initial XML declaration <?xml ... ?> of the document. All XML documents produced by this module will be UTF-8 encoded, as will be all strings output by its functions.
+XML documents passed as parameters to this module's functions must be strings containing bytes/octets, rather than contain characters. They also must be UTF-8 encoded unless an encoding is declared in the initial XML declaration <?xml ... ?> of the document. All XML documents produced by this module will be UTF-8 encoded (bytes/octets). However all other strings which are output by this module's functions and methods (and which are not XML documents) will contain characters rather than bytes/octets.
 
 XML documents to be parsed may not contain the C<< > >> character unencoded in attribute values
 
@@ -799,8 +737,6 @@ C<file> : the function will expect the path to a file containing an XML document
 
 C<complete> : the function's XML output will include an XML declaration (C<< <?xml ... ?>  >>) in the beginning
 
-C<soft> : the function will return undef instead of dying in case of an error during XML parsing
-
 C<internal> : the function will only return the contents of an element in a hashref instead of the element itself (see L</SYNOPSIS> for example)
 
 C<tidy> : the function will return tidy XML
@@ -815,8 +751,6 @@ C<xslt> : will add a <?xml-stylesheet?> link in the XML that's being output, of
 
 C<arrayref> : the function will create a simple arrayref instead of a simple hashref (which will preserve order and elements with duplicate tags)
 
-C<utf8> : the strings which will be returned will have their utf8 flag set (defaults to 0 for compatibility with software built with older versions of this module). The way this module works is that it holds everything in byte format internally (even if you provide it with a utf8 XML string), and then produces utf8 strings or simple structures if (and only if) asked for with this flag. UTF is an important issue, please read C<perldoc utf8> for more.
-
 =head1 FUNCTIONS
 
 =head2 xml_escape($string)
@@ -827,19 +761,19 @@ Returns the same string, but with the C<< < >>, C<< > >>, C<< & >>, C<< " >> and
 
 Returns the XML string in a tidy format (with tabs & newlines)
 
-Optional flags: C<file>, C<complete>, C<indentstring>, C<soft>, C<save>, C<utf8>
+Optional flags: C<file>, C<complete>, C<indentstring>, C<save>
 
 =head2 xml_to_object($raw_xml)
 
 Creates an 'XML::MyXML::Object' object from the raw XML provided
 
-Optional flags: C<file>, C<soft>
+Optional flags: C<file>
 
 =head2 object_to_xml($object)
 
 Creates an XML string from the 'XML::MyXML::Object' object provided
 
-Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>, C<utf8>
+Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>
 
 =head2 simple_to_xml($simple_array_ref)
 
@@ -849,7 +783,9 @@ Produces a raw XML string from either an array reference, a hash reference or a
     [ thing => [ name => 'John', location => [ city => 'New York', country => 'U.S.A.' ] ] ]
     { thing => { name => 'John', location => [ city => 'New York', city => 'Boston', country => 'U.S.A.' ] } }
 
-Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>, C<xslt>, C<utf8>
+All the strings in C<$simple_array_ref> need to contain characters, rather than bytes/octets. The XML output of this function however will be a UTF-8 encoded string (i.e. will contain bytes/octets).
+
+Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>, C<xslt>
 
 =head2 xml_to_simple($raw_xml)
 
@@ -857,11 +793,13 @@ Produces a very simple hash object from the raw XML string provided. An example
 
 Since the object created is a hashref, duplicate keys will be discarded. WARNING: This function only works on very simple XML strings, i.e. children of an element may not consist of both text and elements (child elements will be discarded in that case)
 
-Optional flags: C<internal>, C<strip>, C<file>, C<soft>, C<strip_ns>, C<arrayref>, C<utf8>
+All strings contained in the output simple structure, will contain characters rather than octets/bytes.
+
+Optional flags: C<internal>, C<strip>, C<file>, C<strip_ns>, C<arrayref>
 
 =head2 check_xml($raw_xml)
 
-Returns 1 if the $raw_xml string is valid XML (valid enough to be used by this module), and 0 otherwise.
+Returns true if the $raw_xml string is valid XML (valid enough to be used by this module), and false otherwise.
 
 Optional flags: C<file>
 
@@ -869,68 +807,104 @@ Optional flags: C<file>
 
 =head2 $obj->path("subtag1/subsubtag2[attr1=val1][attr2]/.../subsubsubtagX")
 
-Returns the element specified by the path as an XML::MyXML::Object object. When there are more than one tags with the specified name in the last step of the path, it will return all of them as an array. In scalar context will only return the first one. CSS3-style attribute selectors are allowed in the path next to the tagnames, for example: C<< p[class=big] >> will only return C<< <p> >> elements that contain an attribute called "class" with a value of "big". p[class] on the other hand will return p elements having a "class" attribute, but that attribute can have any value.
+Returns the element specified by the path as an XML::MyXML::Object object. When there are more than one tags with the specified name in the last step of the path, it will return all of them as an array. In scalar context will only return the first one. Simple CSS3-style attribute selectors are allowed in the path next to the tagnames, for example: C<< p[class=big] >> will only return C<< <p> >> elements that contain an attribute called "class" with a value of "big". p[class] on the other hand will return p elements having a "class" attribute, but that attribute can have any value.
+
+An example... To print the last names of all the students from the following XML, do:
+
+    my $xml = <<'EOB';
+    <people>
+        <student>
+            <name>
+                <first>Alex</first>
+                <last>Karelas</last>
+            </name>
+        </student>
+        <student>
+            <name>
+                <first>John</first>
+                <last>Doe</last>
+            </name>
+        </student>
+        <teacher>
+            <name>
+                <first>Mary</first>
+                <last>Poppins</last>
+            </name>
+        </teacher>
+        <teacher>
+            <name>
+                <first>Peter</first>
+                <last>Gabriel</last>
+            </name>
+        </teacher>
+    </people>
+    EOB
+    
+    my $obj = xml_to_object($xml);
+    my @students = $obj->path('student');
+    foreach my $student (@students) {
+        print $student->path('name/last')->value, "\n";
+    }
+
+If you wish to describe the root element in the path as well, prepend it in the path with a slash like so:
+
+    if( $student->path('/student/name/last')->value eq $student->path('name/last')->value ) {
+        print "The two are identical", "\n";
+    }
 
 =head2 $obj->value
 
 When the element represented by the $obj object has only text contents, returns those contents as a string. If the $obj element has no contents, value will return an empty string.
 
-Optional flags: C<strip>, C<utf8>
+Optional flags: C<strip>
 
 =head2 $obj->attr('attrname' [, 'attrvalue'])
 
 Gets/Sets the value of the 'attrname' attribute of the top element. Returns undef if attribute does not exist. If called without the 'attrname' paramter, returns a hash with all attribute => value pairs. If setting with an attrvalue of C<undef>, then removes that attribute entirely.
 
-Optional flags: C<utf8>
+Input parameters and output are all in character strings, rather than octets/bytes.
+
+Optional flags: none
 
 =head2 $obj->tag
 
-Returns the tag of the $obj element (after stripping it from namespaces, unless the C<strip_ns> option is passed as false). E.g. if $obj represents an <rss:item> element, C<< $obj->tag >> will just return the name 'item'.
+Returns the tag of the $obj element. E.g. if $obj represents an <rss:item> element, C<< $obj->tag >> will return the string 'rss:item'.
 Returns undef if $obj doesn't represent a tag.
 
-Optional flags: C<utf8>, C<strip_ns>
+Optional flags: C<strip_ns>
 
 =head2 $obj->simplify
 
 Returns a very simple hashref, like the one returned with C<&XML::MyXML::xml_to_simple>. Same restrictions and warnings apply.
 
-Optional flags: C<internal>, C<strip>, C<strip_ns>, C<arrayref>, C<utf8>
+Optional flags: C<internal>, C<strip>, C<strip_ns>, C<arrayref>
 
 =head2 $obj->to_xml
 
 Returns the XML string of the object, just like calling C<object_to_xml( $obj )>
 
-Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>, C<utf8>
+Optional flags: C<complete>, C<tidy>, C<indentstring>, C<save>
 
 =head2 $obj->to_tidy_xml
 
 Returns the XML string of the object in tidy form, just like calling C<tidy_xml( object_to_xml( $obj ) )>
 
-Optional flags: C<complete>, C<indentstring>, C<save>, C<utf8>
-
-=head2 $obj->delete
-
-Deletes the object and all its children from memory. This is the only way to remove an XML object from memory and clear the RAM, since children and parents refer to each other circularly.
-
-The way it works is by removing references from the object's descendants to their parents.
+Optional flags: C<complete>, C<indentstring>, C<save>
 
 =head1 BUGS
 
-If you don't have a Github account to report your issues at
-L<https://github.com/akarelas/xml-myxml/issues>,
-then feel free to report any bugs or feature requests to
-C<bug-xml-myxml at rt.cpan.org>, or through the web interface at
-L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=XML-MyXML>.
+If you have a Github account, report your issues at
+L<https://github.com/akarelas/xml-myxml/issues>.
 I will be notified, and then you'll automatically be notified of progress on
 your bug as I make changes.
 
 =head1 AUTHOR
 
-Alexander Karelas <karjala@cpan.org>
+Alexander Karelas <karjala@karjala.org>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2013 by Alexander Karelas.
+This software is copyright (c) 2014 by Alexander Karelas.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
@@ -1,24 +1,20 @@
-#!/usr/bin/env perl
-
 use strict;
 use warnings;
-
-use FindBin qw($Bin);
-use lib "$Bin/../lib";
+use utf8;
 
 use Test::More;
-use Test::Deep;
 
+use Encode;
 use File::Temp qw/ tempfile /;
 
 use XML::MyXML qw(:all);
 
-my $xml = "<item><name>Table</name><price><usd>10.00</usd><eur>8.50</eur></price></item>";
+my $xml = encode_utf8("<item><name>Τραπέζι</name><price><usd>10.00</usd><eur>8.50</eur></price></item>");
 my $simple = xml_to_simple($xml);
 
-cmp_deeply($simple, {
+is_deeply($simple, {
 	item => {
-		name => 'Table',
+		name => 'Τραπέζι',
 		price => {
 			usd => '10.00',
 			eur => '8.50',
@@ -28,10 +24,11 @@ cmp_deeply($simple, {
 
 my $obj = xml_to_object($xml);
 is($obj->path('price/eur')->value, '8.50', 'xml_to_object & path & value ok');
+is($obj->path('name')->value, 'Τραπέζι', 'value wide-characters ok');
 
 $simple = {
 	item => [
-		name => 'Table',
+		name => 'Τραπέζι',
 		price => [
 			usd => '10.00',
 			eur => '8.50',
@@ -42,10 +39,21 @@ $simple = {
 my $xml2 = simple_to_xml($simple);
 is($xml2, $xml, 'simple_to_xml ok');
 
-$obj->delete;
+my $tidy_xml = $obj->to_xml({ tidy => 1, indentstring => '  ' });
+my $correct_tidy_xml = <<'EOB';
+<item>
+  <name>Τραπέζι</name>
+  <price>
+    <usd>10.00</usd>
+    <eur>8.50</eur>
+  </price>
+</item>
+EOB
+is($tidy_xml, encode_utf8($correct_tidy_xml), 'tidy with wide-characters works well');
+
 ($obj, $xml2) = ();
 
-is($xml, "<item><name>Table</name><price><usd>10.00</usd><eur>8.50</eur></price></item>", '$xml is unchanged');
+is($xml, encode_utf8("<item><name>Τραπέζι</name><price><usd>10.00</usd><eur>8.50</eur></price></item>"), '$xml is unchanged');
 
 my ($thatfh1, $filename1) = tempfile('myxml-XXXXXXXX', TMPDIR => 1, UNLINK => 1);
 my ($thatfh2, $filename2) = tempfile('myxml-XXXXXXXX', TMPDIR => 1, UNLINK => 1);
@@ -54,9 +62,9 @@ close $thatfh2;
 
 simple_to_xml($simple, { save => $filename1 });
 my $test_smp = xml_to_simple($filename1, { file => 1 });
-cmp_deeply($test_smp, {
+is_deeply($test_smp, {
 	item => {
-		name => 'Table',
+		name => 'Τραπέζι',
 		price => {
 			usd => '10.00',
 			eur => '8.50',
@@ -65,10 +73,21 @@ cmp_deeply($test_smp, {
 }, 'simple_to_xml (save) and xml_to_simple (file) ok');
 
 # TEST NO-STRIPNS TAG
-$xml = "<school:student>Peter</school:student>";
+$xml = encode_utf8("<school:μαθητής>Peter</school:μαθητής>");
 $obj = xml_to_object($xml);
-is($obj->tag, 'student', 'tag stripped_ns ok');
-is($obj->tag({ strip_ns => 0 }), 'school:student', 'tag not stripped_ns ok');
+is($obj->tag, 'school:μαθητής', 'tag not stripped_ns ok 1');
+is($obj->tag({ strip_ns => 0 }), 'school:μαθητής', 'tag not stripped_ns ok 2');
+is($obj->tag({ strip_ns => 1 }), 'μαθητής', 'tag stripped_ns ok');
+
+# TEST STRIP_NS XML_TO_SIMPLE
+$simple = xml_to_simple($xml, { strip_ns => 1 });
+is_deeply($simple, {
+	'μαθητής' => 'Peter',
+}, 'xml_to_simple with strip_ns ok');
+$simple = xml_to_simple($xml);
+is_deeply($simple, {
+	'school:μαθητής' => 'Peter',
+}, 'xml_to_simple without strip_ns ok');
 
 # TEST QUICK-CLOSE
 $simple = { person => { name => undef } };
@@ -80,18 +99,126 @@ is(simple_to_xml($simple), '<person><name>Alex</name></person>', 'slow close wor
 
 # TEST VIEW/CHANGE ATTRS
 note 'test view/change attrs';
-$xml = '<people><person name="george"><spouse>Maria</spouse></person></people>';
+$xml = encode_utf8('<people><person όνομα="γιώργος"><spouse>Maria</spouse></person></people>');
 $obj = xml_to_object($xml);
-is($obj->path('person')->attr('name'), 'george', 'view ok 1');
+is($obj->path('person')->attr('όνομα'), 'γιώργος', 'view ok 1');
 is($obj->path('person')->attr('name2'), undef, 'view ok 2');
-$obj->path('person')->attr('name', 'peter');
-is($obj->to_xml, '<people><person name="peter"><spouse>Maria</spouse></person></people>', 'change ok 1');
-$obj->path('person')->attr('name', undef);
+$obj->path('person')->attr('όνομα', 'πέτρος');
+is($obj->to_xml, encode_utf8('<people><person όνομα="πέτρος"><spouse>Maria</spouse></person></people>'), 'change ok 1');
+$obj->path('person')->attr('όνομα', undef);
 is($obj->to_xml, '<people><person><spouse>Maria</spouse></person></people>', 'change ok 2');
 
 # XML_ESCAPE
-my $string = '<"al&ex\'>';
-is(xml_escape($string), '&lt;&quot;al&amp;ex&apos;&gt;', 'xml string escaped okay');
+my $string = '<"άλ&εξ\'>';
+is(xml_escape($string), '&lt;&quot;άλ&amp;εξ&apos;&gt;', 'xml string escaped okay');
+
+# WRONG UTF-8 PRODUCES ERROR
+$xml = '<person><name>Γιώργος</name></person>';
+$obj = eval { xml_to_object($xml) };
+ok( $@, 'error occured because of wrong UTF-8' );
+
+# CHECK_XML
+ok( check_xml('<person/>'), 'check_xml ok 1' );
+ok( ! check_xml('<person>'), 'check_xml ok 2' );
+
+# CHECK WEAKENED REFS
+note 'checking weakened refs';
+my ($ch1, $ch2);
+{
+	$xml = '<items><item>Table</item><item>Chair</item></items>';
+	$obj = xml_to_object($xml);
+	($ch1, $ch2) = $obj->path('item');
+}
+is($ch1->to_xml, '<item>Table</item>', 'item1 ok');
+is($ch2->to_xml, '<item>Chair</item>', 'item2 ok');
+
+# CHECK DOUBLE-DECODING BUG
+is(XML::MyXML::_decode('&#x26;#65;'), '&#65;', 'double-decoding not occurring');
+
+# TWO MATCHING ENTITIES
+$xml = <<'EOB';
+<!ENTITY copyright "Alex">
+<!ENTITY author "Alex">
+<person>
+	<author>&author;</author>
+	<copy>&copyright;</copy>
+</person>
+EOB
+$simple = xml_to_simple($xml, {internal => 1});
+is_deeply($simple, {
+	author => 'Alex',
+	copy => 'Alex',
+}, 'matching entities ok');
+
+# PATH TESTS
+note 'path tests';
+{
+	$xml = <<'EOB';
+		<people>
+			<student class="B">
+				<name>
+					<first>Alex</first>
+					<last>Karelas</last>
+				</name>
+			</student>
+			<student class="A">
+				<name>
+					<first>John</first>
+					<last>Doe</last>
+				</name>
+			</student>
+			<teacher class="A">
+				<name>
+					<first>Mary</first>
+					<last>Poppins</last>
+				</name>
+			</teacher>
+			<teacher class="A">
+				<name>
+					<first>Peter</first>
+					<last>Gabriel</last>
+				</name>
+			</teacher>
+		</people>
+EOB
+	my $obj = xml_to_object($xml);
+	my @people1 = map $_->simplify({internal => 1}), $obj->path('student');
+	my @people2 = map $_->simplify({internal => 1}), $obj->path('/people/student');
+	is_deeply(\@people1, [
+		{
+			name => {
+				first => 'Alex',
+				last => 'Karelas',
+			},
+		},
+		{
+			name => {
+				first => 'John',
+				last => 'Doe',
+			},
+		},
+	], 'people1 ok');
+	is_deeply(\@people2, \@people1, 'people2 ok');
+	@people1 = map $_->simplify, $obj->path('student[class=A]');
+	@people2 = map $_->simplify, $obj->path('/people/student[class=A]');
+	is_deeply(\@people1, [
+		{
+			student => {
+				name => {
+					first => 'John',
+					last => 'Doe',
+				},
+			},
+		},
+	], 'people1 ok 2');
+	is_deeply(\@people2, \@people1, 'people2 ok 2');
+	@people1 = map $_->simplify, $obj->path('/peoples/student');
+	is_deeply(\@people1, [], 'paths first element compares ok');
+	is($obj->path('/people')->tag, 'people', 'identity path ok');
+	is($obj->path('/')->tag, 'people', 'identity path ok 2');
+}
+
+
 
 
 done_testing();
@@ -1,132 +0,0 @@
-#!/usr/bin/env perl
-
-use strict;
-use warnings;
-use utf8;
-
-use FindBin qw($Bin);
-use lib "$Bin/../lib";
-
-use Test::More;
-use Test::Deep;
-
-use Encode;
-use File::Temp qw/ tempfile /;
-
-use XML::MyXML::II qw(:all);
-
-my $xml = encode_utf8("<item><name>Τραπέζι</name><price><usd>10.00</usd><eur>8.50</eur></price></item>");
-my $simple = xml_to_simple($xml);
-
-cmp_deeply($simple, {
-	item => {
-		name => 'Τραπέζι',
-		price => {
-			usd => '10.00',
-			eur => '8.50',
-		},
-	},
-}, 'xml_to_simple ok');
-
-my $obj = xml_to_object($xml);
-is($obj->path('price/eur')->value, '8.50', 'xml_to_object & path & value ok');
-is($obj->path('name')->value, 'Τραπέζι', 'value wide-characters ok');
-
-$simple = {
-	item => [
-		name => 'Τραπέζι',
-		price => [
-			usd => '10.00',
-			eur => '8.50',
-		],
-	],
-};
-
-my $xml2 = simple_to_xml($simple);
-is($xml2, $xml, 'simple_to_xml ok');
-
-my $tidy_xml = $obj->to_xml({ tidy => 1, indentstring => '  ' });
-my $correct_tidy_xml = <<'EOB';
-<item>
-  <name>Τραπέζι</name>
-  <price>
-    <usd>10.00</usd>
-    <eur>8.50</eur>
-  </price>
-</item>
-EOB
-is($tidy_xml, encode_utf8($correct_tidy_xml), 'tidy with wide-characters works well');
-
-($obj, $xml2) = ();
-
-is($xml, encode_utf8("<item><name>Τραπέζι</name><price><usd>10.00</usd><eur>8.50</eur></price></item>"), '$xml is unchanged');
-
-my ($thatfh1, $filename1) = tempfile('myxml-XXXXXXXX', TMPDIR => 1, UNLINK => 1);
-my ($thatfh2, $filename2) = tempfile('myxml-XXXXXXXX', TMPDIR => 1, UNLINK => 1);
-close $thatfh1;
-close $thatfh2;
-
-simple_to_xml($simple, { save => $filename1 });
-my $test_smp = xml_to_simple($filename1, { file => 1 });
-cmp_deeply($test_smp, {
-	item => {
-		name => 'Τραπέζι',
-		price => {
-			usd => '10.00',
-			eur => '8.50',
-		},
-	},
-}, 'simple_to_xml (save) and xml_to_simple (file) ok');
-
-# TEST NO-STRIPNS TAG
-$xml = encode_utf8("<school:μαθητής>Peter</school:μαθητής>");
-$obj = xml_to_object($xml);
-is($obj->tag, 'school:μαθητής', 'tag not stripped_ns ok 1');
-is($obj->tag({ strip_ns => 0 }), 'school:μαθητής', 'tag not stripped_ns ok 2');
-is($obj->tag({ strip_ns => 1 }), 'μαθητής', 'tag stripped_ns ok');
-
-# TEST QUICK-CLOSE
-$simple = { person => { name => undef } };
-is(simple_to_xml($simple), '<person><name/></person>', 'quick close worked ok 1');
-$simple = { person => { name => '' } };
-is(simple_to_xml($simple), '<person><name/></person>', 'quick close worked ok 2');
-$simple = { person => { name => 'Alex' } };
-is(simple_to_xml($simple), '<person><name>Alex</name></person>', 'slow close worked ok');
-
-# TEST VIEW/CHANGE ATTRS
-note 'test view/change attrs';
-$xml = encode_utf8('<people><person όνομα="γιώργος"><spouse>Maria</spouse></person></people>');
-$obj = xml_to_object($xml);
-is($obj->path('person')->attr('όνομα'), 'γιώργος', 'view ok 1');
-is($obj->path('person')->attr('name2'), undef, 'view ok 2');
-$obj->path('person')->attr('όνομα', 'πέτρος');
-is($obj->to_xml, encode_utf8('<people><person όνομα="πέτρος"><spouse>Maria</spouse></person></people>'), 'change ok 1');
-$obj->path('person')->attr('όνομα', undef);
-is($obj->to_xml, '<people><person><spouse>Maria</spouse></person></people>', 'change ok 2');
-
-# XML_ESCAPE
-my $string = '<"άλ&εξ\'>';
-is(xml_escape($string), '&lt;&quot;άλ&amp;εξ&apos;&gt;', 'xml string escaped okay');
-
-# WRONG UTF-8 PRODUCES ERROR
-$xml = '<person><name>Γιώργος</name></person>';
-$obj = eval { xml_to_object($xml) };
-ok( $@, 'error occured because of wrong UTF-8' );
-
-# CHECK_XML
-ok( check_xml('<person/>'), 'check_xml ok 1' );
-ok( ! check_xml('<person>'), 'check_xml ok 2' );
-
-# CHECK WEAKENED REFS
-note 'checking weakened refs';
-my ($ch1, $ch2);
-{
-	$xml = '<items><item>Table</item><item>Chair</item></items>';
-	$obj = xml_to_object($xml);
-	($ch1, $ch2) = $obj->path('item');
-}
-is($ch1->to_xml, '<item>Table</item>', 'item1 ok');
-is($ch2->to_xml, '<item>Chair</item>', 'item2 ok');
-
-
-done_testing();