Add built local::lib
[catagits/Gitalist.git] / local-lib5 / man / man3 / XML::Simple::FAQ.3pm
diff --git a/local-lib5/man/man3/XML::Simple::FAQ.3pm b/local-lib5/man/man3/XML::Simple::FAQ.3pm
new file mode 100644 (file)
index 0000000..2402333
--- /dev/null
@@ -0,0 +1,738 @@
+.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.10)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "XML::Simple::FAQ 3"
+.TH XML::Simple::FAQ 3 "2004-11-20" "perl v5.8.7" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "Frequently Asked Questions about XML::Simple"
+.IX Header "Frequently Asked Questions about XML::Simple"
+.SH "Basics"
+.IX Header "Basics"
+.SS "What is XML::Simple designed to be used for?"
+.IX Subsection "What is XML::Simple designed to be used for?"
+XML::Simple is a Perl module that was originally developed as a tool for
+reading and writing configuration data in \s-1XML\s0 format.  You can use it for
+many other purposes that involve storing and retrieving structured data in
+\&\s-1XML\s0.
+.PP
+You might also find XML::Simple a good starting point for playing with \s-1XML\s0
+from Perl.  It doesn't have a steep learning curve and if you outgrow its
+capabilities there are plenty of other Perl/XML modules to 'step up' to.
+.SS "Why store configuration data in \s-1XML\s0 anyway?"
+.IX Subsection "Why store configuration data in XML anyway?"
+The many advantages of using \s-1XML\s0 format for configuration data include:
+.IP "\(bu" 4
+Using existing \s-1XML\s0 parsing tools requires less development time, is easier
+and more robust than developing your own config file parsing code
+.IP "\(bu" 4
+\&\s-1XML\s0 can represent relationships between pieces of data, such as nesting of
+sections to arbitrary levels (not easily done with .INI files for example)
+.IP "\(bu" 4
+\&\s-1XML\s0 is basically just text, so you can easily edit a config file (easier than
+editing a Win32 registry)
+.IP "\(bu" 4
+\&\s-1XML\s0 provides standard solutions for handling character sets and encoding
+beyond basic \s-1ASCII\s0 (important for internationalization)
+.IP "\(bu" 4
+If it becomes necessary to change your configuration file format, there are
+many tools available for performing transformations on \s-1XML\s0 files
+.IP "\(bu" 4
+\&\s-1XML\s0 is an open standard (the world does not need more proprietary binary
+file formats)
+.IP "\(bu" 4
+Taking the extra step of developing a \s-1DTD\s0 allows the format of configuration
+files to be validated before your program reads them (not directly supported
+by XML::Simple)
+.IP "\(bu" 4
+Combining a \s-1DTD\s0 with a good \s-1XML\s0 editor can give you a \s-1GUI\s0 config editor for
+minimal coding effort
+.SS "What isn't XML::Simple good for?"
+.IX Subsection "What isn't XML::Simple good for?"
+The main limitation of XML::Simple is that it does not work with 'mixed
+content' (see the next question).  If you consider your \s-1XML\s0 files contain
+marked up text rather than structured data, you should probably use another
+module.
+.PP
+If you are working with very large \s-1XML\s0 files, XML::Simple's approach of
+representing the whole file in memory as a 'tree' data structure may not be
+suitable.
+.SS "What is mixed content?"
+.IX Subsection "What is mixed content?"
+Consider this example \s-1XML:\s0
+.PP
+.Vb 3
+\&  <document>
+\&    <para>This is <em>mixed</em> content.</para>
+\&  </document>
+.Ve
+.PP
+This is said to be mixed content, because the <para> element contains
+both character data (text content) and nested elements.
+.PP
+Here's some more \s-1XML:\s0
+.PP
+.Vb 5
+\&  <person>
+\&    <first_name>Joe</first_name>
+\&    <last_name>Bloggs</last_name>
+\&    <dob>25\-April\-1969</dob>
+\&  </person>
+.Ve
+.PP
+This second example is not generally considered to be mixed content.  The
+<first_name>, <last_name> and <dob> elements contain
+only character data and the  <person> element contains only nested
+elements.  (Note: Strictly speaking, the whitespace between the nested
+elements is character data, but it is ignored by XML::Simple).
+.SS "Why doesn't XML::Simple handle mixed content?"
+.IX Subsection "Why doesn't XML::Simple handle mixed content?"
+Because if it did, it would no longer be simple :\-)
+.PP
+Seriously though, there are plenty of excellent modules that allow you to
+work with mixed content in a variety of ways.  Handling mixed content
+correctly is not easy and by ignoring these issues, XML::Simple is able to
+present an \s-1API\s0 without a steep learning curve.
+.SS "Which Perl modules do handle mixed content?"
+.IX Subsection "Which Perl modules do handle mixed content?"
+Every one of them except XML::Simple :\-)
+.PP
+If you're looking for a recommendation, I'd suggest you look at the Perl-XML
+\&\s-1FAQ\s0 at:
+.PP
+.Vb 1
+\&  http://perl\-xml.sourceforge.net/faq/
+.Ve
+.SH "Installation"
+.IX Header "Installation"
+.SS "How do I install XML::Simple?"
+.IX Subsection "How do I install XML::Simple?"
+If you're running ActiveState Perl, you've probably already got XML::Simple 
+(although you may want to upgrade to version 1.09 or better for \s-1SAX\s0 support).
+.PP
+If you do need to install XML::Simple, you'll need to install an \s-1XML\s0 parser
+module first.  Install either XML::Parser (which you may have already) or
+\&\s-1XML::SAX\s0.  If you install both, \s-1XML::SAX\s0 will be used by default.
+.PP
+Once you have a parser installed ...
+.PP
+On Unix systems, try:
+.PP
+.Vb 1
+\&  perl \-MCPAN \-e \*(Aqinstall XML::Simple\*(Aq
+.Ve
+.PP
+If that doesn't work, download the latest distribution from
+ftp://ftp.cpan.org/pub/CPAN/authors/id/G/GR/GRANTM , unpack it and run these
+commands:
+.PP
+.Vb 4
+\&  perl Makefile.PL
+\&  make
+\&  make test
+\&  make install
+.Ve
+.PP
+On Win32, if you have a recent build of ActiveState Perl (618 or better) try
+this command:
+.PP
+.Vb 1
+\&  ppm install XML::Simple
+.Ve
+.PP
+If that doesn't work, you really only need the Simple.pm file, so extract it
+from the .tar.gz file (eg: using WinZIP) and save it in the \esite\elib\eXML 
+directory under your Perl installation (typically C:\ePerl).
+.SS "I'm trying to install XML::Simple and 'make test' fails"
+.IX Subsection "I'm trying to install XML::Simple and 'make test' fails"
+Is the directory where you've unpacked XML::Simple mounted from a file server
+using \s-1NFS\s0, \s-1SMB\s0 or some other network file sharing?  If so, that may cause
+errors in the the following test scripts:
+.PP
+.Vb 3
+\&  3_Storable.t
+\&  4_MemShare.t
+\&  5_MemCopy.t
+.Ve
+.PP
+The test suite is designed to exercise the boundary conditions of all
+XML::Simple's functionality and these three scripts exercise the caching
+functions.  If XML::Simple is asked to parse a file for which it has a cached
+copy of a previous parse, then it compares the timestamp on the \s-1XML\s0 file with
+the timestamp on the cached copy.  If the cached copy is *newer* then it will
+be used.  If the cached copy is older or the same age then the file is
+re-parsed.  The test scripts will get confused by networked filesystems if
+the workstation and server system clocks are not synchronised (to the
+second).
+.PP
+If you get an error in one of these three test scripts but you don't plan to
+use the caching options (they're not enabled by default), then go right ahead
+and run 'make install'.  If you do plan to use caching, then try unpacking
+the distribution on local disk and doing the build/test there.
+.PP
+It's probably not a good idea to use the caching options with networked
+filesystems in production.  If the file server's clock is ahead of the local
+clock, XML::Simple will re-parse files when it could have used the cached
+copy.  However if the local clock is ahead of the file server clock and a
+file is changed immediately after it is cached, the old cached copy will be
+used.
+.PP
+Is one of the three test scripts (above) failing but you're not running on
+a network filesystem?  Are you running Win32?  If so, you may be seeing a bug
+in Win32 where writes to a file do not affect its modfication timestamp.
+.PP
+If none of these scenarios match your situation, please confirm you're
+running the latest version of XML::Simple and then email the output of
+\&'make test' to me at grantm@cpan.org
+.SS "Why is XML::Simple so slow?"
+.IX Subsection "Why is XML::Simple so slow?"
+If you find that XML::Simple is very slow reading \s-1XML\s0, the most likely reason
+is that you have \s-1XML::SAX\s0 installed but no additional \s-1SAX\s0 parser module.  The
+\&\s-1XML::SAX\s0 distribution includes an \s-1XML\s0 parser written entirely in Perl.  This is
+very portable but not very fast.  For better performance install either
+XML::SAX::Expat or XML::LibXML.
+.SH "Usage"
+.IX Header "Usage"
+.SS "How do I use XML::Simple?"
+.IX Subsection "How do I use XML::Simple?"
+If you had an \s-1XML\s0 document called /etc/appconfig/foo.xml you could 'slurp' it
+into a simple data structure (typically a hashref) with these lines of code:
+.PP
+.Vb 1
+\&  use XML::Simple;
+\&
+\&  my $config = XMLin(\*(Aq/etc/appconfig/foo.xml\*(Aq);
+.Ve
+.PP
+The \fIXMLin()\fR function accepts options after the filename.
+.SS "There are so many options, which ones do I really need to know about?"
+.IX Subsection "There are so many options, which ones do I really need to know about?"
+Although you can get by without using any options, you shouldn't even
+consider using XML::Simple in production until you know what these two
+options do:
+.IP "\(bu" 4
+forcearray
+.IP "\(bu" 4
+keyattr
+.PP
+The reason you really need to read about them is because the default values
+for these options will trip you up if you don't.  Although everyone agrees
+that these defaults are not ideal, there is not wide agreement on what they
+should be changed to.  The answer therefore is to read about them (see below)
+and select values which are right for you.
+.SS "What is the forcearray option all about?"
+.IX Subsection "What is the forcearray option all about?"
+Consider this \s-1XML\s0 in a file called ./person.xml:
+.PP
+.Vb 7
+\&  <person>
+\&    <first_name>Joe</first_name>
+\&    <last_name>Bloggs</last_name>
+\&    <hobbie>bungy jumping</hobbie>
+\&    <hobbie>sky diving</hobbie>
+\&    <hobbie>knitting</hobbie>
+\&  </person>
+.Ve
+.PP
+You could read it in with this line:
+.PP
+.Vb 1
+\&  my $person = XMLin(\*(Aq./person.xml\*(Aq);
+.Ve
+.PP
+Which would give you a data structure like this:
+.PP
+.Vb 5
+\&  $person = {
+\&    \*(Aqfirst_name\*(Aq => \*(AqJoe\*(Aq,
+\&    \*(Aqlast_name\*(Aq  => \*(AqBloggs\*(Aq,
+\&    \*(Aqhobbie\*(Aq     => [ \*(Aqbungy jumping\*(Aq, \*(Aqsky diving\*(Aq, \*(Aqknitting\*(Aq ]
+\&  };
+.Ve
+.PP
+The <first_name> and <last_name> elements are represented as
+simple scalar values which you could refer to like this:
+.PP
+.Vb 1
+\&  print "$person\->{first_name} $person\->{last_name}\en";
+.Ve
+.PP
+The <hobbie> elements are represented as an array \- since there is
+more than one.  You could refer to the first one like this:
+.PP
+.Vb 1
+\&  print $person\->{hobbie}\->[0], "\en";
+.Ve
+.PP
+Or the whole lot like this:
+.PP
+.Vb 1
+\&  print join(\*(Aq, \*(Aq, @{$person\->{hobbie}} ), "\en";
+.Ve
+.PP
+The catch is, that these last two lines of code will only work for people
+who have more than one hobbie.  If there is only one <hobbie>
+element, it will be represented as a simple scalar (just like
+<first_name> and <last_name>).  Which might lead you to write
+code like this:
+.PP
+.Vb 6
+\&  if(ref($person\->{hobbie})) {
+\&    print join(\*(Aq, \*(Aq, @{$person\->{hobbie}} ), "\en";
+\&  }
+\&  else {
+\&    print $person\->{hobbie}, "\en";
+\&  }
+.Ve
+.PP
+Don't do that.
+.PP
+One alternative approach is to set the forcearray option to a true value:
+.PP
+.Vb 1
+\&  my $person = XMLin(\*(Aq./person.xml\*(Aq, forcearray => 1);
+.Ve
+.PP
+Which will give you a data structure like this:
+.PP
+.Vb 5
+\&  $person = {
+\&    \*(Aqfirst_name\*(Aq => [ \*(AqJoe\*(Aq ],
+\&    \*(Aqlast_name\*(Aq  => [ \*(AqBloggs\*(Aq ],
+\&    \*(Aqhobbie\*(Aq     => [ \*(Aqbungy jumping\*(Aq, \*(Aqsky diving\*(Aq, \*(Aqknitting\*(Aq ]
+\&  };
+.Ve
+.PP
+Then you can use this line to refer to all the list of hobbies even if there
+was only one:
+.PP
+.Vb 1
+\&  print join(\*(Aq, \*(Aq, @{$person\->{hobbie}} ), "\en";
+.Ve
+.PP
+The downside of this approach is that the <first_name> and
+<last_name> elements will also always be represented as arrays even
+though there will never be more than one:
+.PP
+.Vb 1
+\&  print "$person\->{first_name}\->[0] $person\->{last_name}\->[0]\en";
+.Ve
+.PP
+This might be \s-1OK\s0 if you change the \s-1XML\s0 to use attributes for things that
+will always be singular and nested elements for things that may be plural:
+.PP
+.Vb 3
+\&  <person first_name="Jane" last_name="Bloggs">
+\&    <hobbie>motorcycle maintenance</hobbie>
+\&  </person>
+.Ve
+.PP
+On the other hand, if you prefer not to use attributes, then you could
+specify that any <hobbie> elements should always be represented as
+arrays and all other nested elements should be simple scalar values unless
+there is more than one:
+.PP
+.Vb 1
+\&  my $person = XMLin(\*(Aq./person.xml\*(Aq, forcearray => [ \*(Aqhobbie\*(Aq ]);
+.Ve
+.PP
+The forcearray option accepts a list of element names which should always
+be forced to an array representation:
+.PP
+.Vb 1
+\&  forcearray => [ qw(hobbie qualification childs_name) ]
+.Ve
+.PP
+See the XML::Simple manual page for more information.
+.SS "What is the keyattr option all about?"
+.IX Subsection "What is the keyattr option all about?"
+Consider this sample \s-1XML:\s0
+.PP
+.Vb 5
+\&  <catalog>
+\&    <part partnum="1842334" desc="High pressure flange" price="24.50" />
+\&    <part partnum="9344675" desc="Threaded gasket"      price="9.25" />
+\&    <part partnum="5634896" desc="Low voltage washer"   price="12.00" />
+\&  </catalog>
+.Ve
+.PP
+You could slurp it in with this code:
+.PP
+.Vb 1
+\&  my $catalog = XMLin(\*(Aq./catalog.xml\*(Aq);
+.Ve
+.PP
+Which would return a data structure like this:
+.PP
+.Vb 10
+\&  $catalog = {
+\&      \*(Aqpart\*(Aq => [
+\&          {
+\&            \*(Aqpartnum\*(Aq => \*(Aq1842334\*(Aq,
+\&            \*(Aqdesc\*(Aq    => \*(AqHigh pressure flange\*(Aq,
+\&            \*(Aqprice\*(Aq   => \*(Aq24.50\*(Aq
+\&          },
+\&          {
+\&            \*(Aqpartnum\*(Aq => \*(Aq9344675\*(Aq,
+\&            \*(Aqdesc\*(Aq    => \*(AqThreaded gasket\*(Aq,
+\&            \*(Aqprice\*(Aq   => \*(Aq9.25\*(Aq
+\&          },
+\&          {
+\&            \*(Aqpartnum\*(Aq => \*(Aq5634896\*(Aq,
+\&            \*(Aqdesc\*(Aq    => \*(AqLow voltage washer\*(Aq,
+\&            \*(Aqprice\*(Aq   => \*(Aq12.00\*(Aq
+\&          }
+\&      ]
+\&  };
+.Ve
+.PP
+Then you could access the description of the first part in the catalog
+with this code:
+.PP
+.Vb 1
+\&  print $catalog\->{part}\->[0]\->{desc}, "\en";
+.Ve
+.PP
+However, if you wanted to access the description of the part with the
+part number of \*(L"9344675\*(R" then you'd have to code a loop like this:
+.PP
+.Vb 6
+\&  foreach my $part (@{$catalog\->{part}}) {
+\&    if($part\->{partnum} eq \*(Aq9344675\*(Aq) {
+\&      print $part\->{desc}, "\en";
+\&      last;
+\&    }
+\&  }
+.Ve
+.PP
+The knowledge that each <part> element has a unique partnum attribute
+allows you to eliminate this search.  You can pass this knowledge on to
+XML::Simple like this:
+.PP
+.Vb 1
+\&  my $catalog = XMLin($xml, keyattr => [\*(Aqpartnum\*(Aq]);
+.Ve
+.PP
+Which will return a data structure like this:
+.PP
+.Vb 7
+\&  $catalog = {
+\&    \*(Aqpart\*(Aq => {
+\&      \*(Aq5634896\*(Aq => { \*(Aqdesc\*(Aq => \*(AqLow voltage washer\*(Aq,   \*(Aqprice\*(Aq => \*(Aq12.00\*(Aq },
+\&      \*(Aq1842334\*(Aq => { \*(Aqdesc\*(Aq => \*(AqHigh pressure flange\*(Aq, \*(Aqprice\*(Aq => \*(Aq24.50\*(Aq },
+\&      \*(Aq9344675\*(Aq => { \*(Aqdesc\*(Aq => \*(AqThreaded gasket\*(Aq,      \*(Aqprice\*(Aq => \*(Aq9.25\*(Aq  }
+\&    }
+\&  };
+.Ve
+.PP
+XML::Simple has been able to transform \f(CW$catalog\fR\->{part} from an arrayref to
+a hashref (keyed on partnum).  This transformation is called 'array folding'.
+.PP
+Through the use of array folding, you can now index directly to the
+description of the part you want:
+.PP
+.Vb 1
+\&  print $catalog\->{part}\->{9344675}\->{desc}, "\en";
+.Ve
+.PP
+The 'keyattr' option also enables array folding when the unique key is in a
+nested element rather than an attribute.  eg:
+.PP
+.Vb 10
+\&  <catalog>
+\&    <part>
+\&      <partnum>1842334</partnum>
+\&      <desc>High pressure flange</desc>
+\&      <price>24.50</price>
+\&    </part>
+\&    <part>
+\&      <partnum>9344675</partnum>
+\&      <desc>Threaded gasket</desc>
+\&      <price>9.25</price>
+\&    </part>
+\&    <part>
+\&      <partnum>5634896</partnum>
+\&      <desc>Low voltage washer</desc>
+\&      <price>12.00</price>
+\&    </part>
+\&  </catalog>
+.Ve
+.PP
+See the XML::Simple manual page for more information.
+.SS "So what's the catch with 'keyattr'?"
+.IX Subsection "So what's the catch with 'keyattr'?"
+One thing to watch out for is that you might get array folding even if you
+don't supply the keyattr option.  The default value for this option is:
+.PP
+.Vb 1
+\&  [ \*(Aqname\*(Aq, \*(Aqkey\*(Aq, \*(Aqid\*(Aq]
+.Ve
+.PP
+Which means if your \s-1XML\s0 elements have a 'name', 'key' or 'id' attribute (or
+nested element) then they may get folded on those values.  This means that
+you can take advantage of array folding simply through careful choice of
+attribute names.  On the hand, if you really don't want array folding at all,
+you'll need to set 'key attr to an empty list:
+.PP
+.Vb 1
+\&  my $ref = XMLin($xml, keyattr => []);
+.Ve
+.PP
+A second 'gotcha' is that array folding only works on arrays.  That might
+seem obvious, but if there's only one record in your \s-1XML\s0 and you didn't set
+the 'forcearray' option then it won't be represented as an array and
+consequently won't get folded into a hash.  The moral is that if you're
+using array folding, you should always turn on the forcearray option.
+.PP
+You probably want to be as specific as you can be too.  For instance, the
+safest way to parse the <catalog> example above would be:
+.PP
+.Vb 2
+\&  my $catalog = XMLin($xml, keyattr => { part => \*(Aqpartnum\*(Aq},
+\&                            forcearray => [\*(Aqpart\*(Aq]);
+.Ve
+.PP
+By using the hashref for keyattr, you can specify that only <part>
+elements should be folded on the 'partnum' attribute (and that the
+<part> elements should not be folded on any other attribute).
+.PP
+By supplying a list of element names for forcearray, you're ensuring that
+folding will work even if there's only one <part>.  You're also
+ensuring that if the 'partnum' unique key is supplied in a nested element
+then that element won't get forced to an array too.
+.SS "How do I know what my data structure should look like?"
+.IX Subsection "How do I know what my data structure should look like?"
+The rules are fairly straightforward:
+.IP "\(bu" 4
+each element gets represented as a hash
+.IP "\(bu" 4
+unless it contains only text, in which case it'll be a simple scalar value
+.IP "\(bu" 4
+or unless there's more than one element with the same name, in which case
+they'll be represented as an array
+.IP "\(bu" 4
+unless you've got array folding enabled, in which case they'll be folded into
+a hash
+.IP "\(bu" 4
+empty elements (no text contents \fBand\fR no attributes) will either be
+represented as an empty hash, an empty string or undef \- depending on the value
+of the 'suppressempty' option.
+.PP
+If you're in any doubt, use Data::Dumper, eg:
+.PP
+.Vb 2
+\&  use XML::Simple;
+\&  use Data::Dumper;
+\&  
+\&  my $ref = XMLin($xml);
+\&
+\&  print Dumper($ref);
+.Ve
+.SS "I'm getting 'Use of uninitialized value' warnings"
+.IX Subsection "I'm getting 'Use of uninitialized value' warnings"
+You're probably trying to index into a non-existant hash key \- try
+Data::Dumper.
+.SS "I'm getting a 'Not an \s-1ARRAY\s0 reference' error"
+.IX Subsection "I'm getting a 'Not an ARRAY reference' error"
+Something that you expect to be an array is not.  The two most likely causes
+are that you forgot to use 'forcearray' or that the array got folded into a
+hash \- try Data::Dumper.
+.SS "I'm getting a 'No such array field' error"
+.IX Subsection "I'm getting a 'No such array field' error"
+Something that you expect to be a hash is actually an array.  Perhaps array
+folding failed because one element was missing the key attribute \- try
+Data::Dumper.
+.SS "I'm getting an 'Out of memory' error"
+.IX Subsection "I'm getting an 'Out of memory' error"
+Something in the data structure is not as you expect and Perl may be trying
+unsuccessfully to autovivify things \- try Data::Dumper.
+.PP
+If you're already using Data::Dumper, try calling \fIDumper()\fR immediately after
+\&\fIXMLin()\fR \- ie: before you attempt to access anything in the data structure.
+.SS "My element order is getting jumbled up"
+.IX Subsection "My element order is getting jumbled up"
+If you read an \s-1XML\s0 file with \fIXMLin()\fR and then write it back out with
+\&\fIXMLout()\fR, the order of the elements will likely be different.  (However, if
+you read the file back in with \fIXMLin()\fR you'll get the same Perl data
+structure).
+.PP
+The reordering happens because XML::Simple uses hashrefs to store your data
+and Perl hashes do not really have any order.
+.PP
+It is possible that a future version of XML::Simple will use Tie::IxHash
+to store the data in hashrefs which do retain the order.  However this will
+not fix all cases of element order being lost.
+.PP
+If your application really is sensitive to element order, don't use
+XML::Simple (and don't put order-sensitive values in attributes).
+.SS "XML::Simple turns nested elements into attributes"
+.IX Subsection "XML::Simple turns nested elements into attributes"
+If you read an \s-1XML\s0 file with \fIXMLin()\fR and then write it back out with
+\&\fIXMLout()\fR, some data which was originally stored in nested elements may end up
+in attributes.  (However, if you read the file back in with \fIXMLin()\fR you'll
+get the same Perl data structure).
+.PP
+There are a number of ways you might handle this:
+.IP "\(bu" 4
+use the 'forcearray' option with \fIXMLin()\fR
+.IP "\(bu" 4
+use the 'noattr' option with \fIXMLout()\fR
+.IP "\(bu" 4
+live with it
+.IP "\(bu" 4
+don't use XML::Simple
+.SS "Why does \fIXMLout()\fP insert <name> elements (or attributes)?"
+.IX Subsection "Why does XMLout() insert <name> elements (or attributes)?"
+Try setting keyattr => [].
+.PP
+When you call \fIXMLin()\fR to read \s-1XML\s0, the 'keyattr' option controls whether arrays
+get 'folded' into hashes.  Similarly, when you call \fIXMLout()\fR, the 'keyattr'
+option controls whether hashes get 'unfolded' into arrays.  As described above,
+\&'keyattr' is enabled by default.
+.SS "Why are empty elements represented as empty hashes?"
+.IX Subsection "Why are empty elements represented as empty hashes?"
+An element is always represented as a hash unless it contains only text, in
+which case it is represented as a scalar string.
+.PP
+If you would prefer empty elements to be represented as empty strings or the
+undefined value, set the 'suppressempty' option to '' or undef respectively.
+.SS "Why is ParserOpts deprecated?"
+.IX Subsection "Why is ParserOpts deprecated?"
+The \f(CW\*(C`ParserOpts\*(C'\fR option is a remnant of the time when XML::Simple only worked
+with the XML::Parser \s-1API\s0.  Its value is completely ignored if you're using a
+\&\s-1SAX\s0 parser, so writing code which relied on it would bar you from taking
+advantage of \s-1SAX\s0.
+.PP
+Even if you are using XML::Parser, it is seldom necessary to pass options to
+the parser object.  A number of people have written to say they use this option
+to set XML::Parser's \f(CW\*(C`ProtocolEncoding\*(C'\fR option.  Don't do that, it's wrong,
+Wrong, \s-1WRONG\s0!  Fix the \s-1XML\s0 document so that it's well-formed and you won't have
+a problem.
+.PP
+Having said all of that, as long as XML::Simple continues to support the
+XML::Parser \s-1API\s0, this option will not be removed.  There are currently no plans
+to remove support for the XML::Parser \s-1API\s0.