.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" 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" '' . ds C` . ds C' '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 >0, 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. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "XML::Smart 3pm" .TH XML::Smart 3pm "2022-11-19" "perl v5.36.0" "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 "NAME" XML::Smart \- A smart, easy and powerful way to access or create XML from fiels, data and URLs. .SH "VERSION" .IX Header "VERSION" Version 1.78 .SH "SYNOPSIS" .IX Header "SYNOPSIS" This module provides an easy way to access/create \s-1XML\s0 data. It's based on a \s-1HASH\s0 tree created from the \s-1XML\s0 data, and enables dynamic access to it through the standard Perl syntax for Hash and Array, without necessarily caring about which you are working with. In other words, \fBeach point in the tree works as a Hash and an Array at the same time\fR! .PP This module additionally provides special resources such as: search for nodes by attribute, select an attribute value in each multiple node, change the returned format, and so on. .PP The module also automatically handles binary data (encoding/decoding to/from base64), \&\s-1CDATA\s0 (like contents with ) and Unicode. It can be used to create \s-1XML\s0 files, load \s-1XML\s0 from the Web ( just by using an \s-1URL\s0 as the file path ) and has an easy way to send \s-1XML\s0 data through sockets \- just adding the length of the data in the header. .PP You can use \fIXML::Smart\fR with XML::Parser, or with the 2 standard parsers of XML::Smart: .IP "\fIXML::Smart::Parser\fR" 10 .IX Item "XML::Smart::Parser" .PD 0 .IP "\fIXML::Smart::HTMLParser\fR." 10 .IX Item "XML::Smart::HTMLParser." .PD .PP \&\fIXML::Smart::HTMLParser\fR can be used to load/parse wild/bad \s-1XML\s0 data, or \s-1HTML\s0 tags. .SH "Tutorial and F.A.Q." .IX Header "Tutorial and F.A.Q." You can find some extra documents about \fIXML::Smart\fR at: .IP "XML::Smart::Tutorial \- Tutorial and examples for XML::Smart." 2 .IX Item "XML::Smart::Tutorial - Tutorial and examples for XML::Smart." .PD 0 .IP "XML::Smart::FAQ \- Frequently Asked Questions about XML::Smart." 2 .IX Item "XML::Smart::FAQ - Frequently Asked Questions about XML::Smart." .PD .SH "USAGE" .IX Header "USAGE" .Vb 2 \& ## Create the object and load the file: \& my $XML = XML::Smart\->new(\*(Aqfile.xml\*(Aq) ; \& \& ## Force the use of the parser \*(AqXML::Smart::Parser\*(Aq. \& my $XML = XML::Smart\->new(\*(Aqfile.xml\*(Aq , \*(AqXML::Smart::Parser\*(Aq) ; \& \& ## Get from the web: \& my $XML = XML::Smart\->new(\*(Aqhttp://www.perlmonks.org/index.pl?node_id=16046\*(Aq) ; \& \& ## Cut the root: \& $XML = $XML\->cut_root ; \& \& ## Or change the root: \& $XML = $XML\->{hosts} ; \& \& ## Get the address [0] of server [0]: \& my $srv0_addr0 = $XML\->{server}[0]{address}[0] ; \& ## ...or... \& my $srv0_addr0 = $XML\->{server}{address} ; \& \& ## Get the server where the attibute \*(Aqtype\*(Aq eq \*(Aqsuse\*(Aq: \& my $server = $XML\->{server}(\*(Aqtype\*(Aq,\*(Aqeq\*(Aq,\*(Aqsuse\*(Aq) ; \& \& ## Get the address again: \& my $addr1 = $server\->{address}[1] ; \& ## ...or... \& my $addr1 = $XML\->{server}(\*(Aqtype\*(Aq,\*(Aqeq\*(Aq,\*(Aqsuse\*(Aq){address}[1] ; \& \& ## Get all the addresses of a server: \& my @addrs = @{$XML\->{server}{address}} ; \& ## ...or... \& my @addrs = $XML\->{server}{address}(\*(Aq@\*(Aq) ; \& \& ## Get a list of types of all the servers: \& my @types = $XML\->{server}(\*(Aq[@]\*(Aq,\*(Aqtype\*(Aq) ; \& \& ## Add a new server node: \& my $newsrv = { \& os => \*(AqLinux\*(Aq , \& type => \*(AqMandrake\*(Aq , \& version => 8.9 , \& address => [qw(192.168.3.201 192.168.3.202)] \& } ; \& \& push(@{$XML\->{server}} , $newsrv) ; \& \& ## Get/rebuild the XML data: \& my $xmldata = $XML\->data ; \& \& ## Save in some file: \& $XML\->save(\*(Aqnewfile.xml\*(Aq) ; \& \& ## Send through a socket: \& print $socket $XML\->data(length => 1) ; ## show the \*(Aqlength\*(Aq in the XML header to the \& ## socket know the amount of data to read. \& \& _\|_DATA_\|_ \& \& \& \&
192.168.0.1
\&
192.168.0.2
\&
\& \&
192.168.1.10
\&
192.168.1.20
\&
\& \&
.Ve .SH "METHODS" .IX Header "METHODS" .SS "new (FILE|DATA|URL , \s-1PARSER , OPTIONS\s0)" .IX Subsection "new (FILE|DATA|URL , PARSER , OPTIONS)" Create a \s-1XML\s0 object. .PP \&\fBArguments:\fR .IP "FILE|DATA|URL" 10 .IX Item "FILE|DATA|URL" The first argument can be: .Sp .Vb 4 \& \- XML data as string. \& \- File path. \& \- File Handle (GLOB). \& \- URL (Need LWP::UserAgent). .Ve .Sp If not passed, a null \s-1XML\s0 tree is started, where you should create your own \&\s-1XML\s0 data, than build/save/send it. .IP "\s-1PARSER\s0 \fB(optional)\fR" 10 .IX Item "PARSER (optional)" Set the \s-1XML\s0 parser to use. Options: .Sp .Vb 3 \& XML::Parser \& XML::Smart::Parser \& XML::Smart::HTMLParser .Ve .Sp \&\fIXML::Smart::Parser\fR can only handle basic \s-1XML\s0 data (not supported \s-1PCDATA,\s0 and any header like: \s-1ENTITY, NOTATION,\s0 etc...), but is a good choice when you don't want to install big modules to parse \s-1XML,\s0 since it comes with the main module. But it still can handle \s-1CDATA\s0 and binary data. .Sp ** See \fI\*(L"\s-1PARSING HTML\s0 as \s-1XML\*(R"\s0\fR for \fBXML::Smart::HTMLParser\fR. .Sp Aliases for the options: .Sp .Vb 2 \& SMART|REGEXP => XML::Smart::Parser \& HTML => XML::Smart::HTMLParser .Ve .Sp \&\fIDefault:\fR .Sp If not set it will look for XML::Parser and load it. If XML::Parser can't be loaded it will use XML::Smart::Parser, which is actually a clone of XML::Parser::Lite with some fixes. .IP "\s-1OPTIONS\s0" 10 .IX Item "OPTIONS" You can force the uper case and lower case for tags (nodes) and arguments (attributes), and other extra things. .RS 10 .IP "lowtag" 10 .IX Item "lowtag" Make the tags lower case. .IP "lowarg" 10 .IX Item "lowarg" Make the arguments lower case. .IP "upertag" 10 .IX Item "upertag" Make the tags uper case. .IP "uperarg" 10 .IX Item "uperarg" Make the arguments uper case. .IP "arg_single" 10 .IX Item "arg_single" Set the value of arguments to 1 when they have a \fIundef\fR value. .Sp \&\fI** This option will work only when the \s-1XML\s0 is parsed by \f(BIXML::Smart::HTMLParser\fI, since it accept arguments without values:\fR .Sp .Vb 5 \& my $xml = new XML::Smart( \& \*(Aq\*(Aq , \& \*(AqXML::Smart::HTMLParser\*(Aq , \& arg_single => 1 , \& ) ; .Ve .Sp In this example the option \*(L"arg_single\*(R" was used, what will define \fIflag\fR to 1, but \fIarg1\fR will still have a null string value (""). .Sp Here's the tree of the example above: .Sp .Vb 6 \& \*(Aqroot\*(Aq => { \& \*(Aqfoo\*(Aq => { \& \*(Aqflag\*(Aq => 1, \& \*(Aqarg1\*(Aq => \*(Aq\*(Aq \& }, \& }, .Ve .IP "use_spaces" 10 .IX Item "use_spaces" Accept contents that have only spaces. .IP "on_start (\s-1CODE\s0) \fI*optional\fR" 10 .IX Item "on_start (CODE) *optional" Code/sub to call on start a tag. .Sp \&\fI** This will be called after XML::Smart parse the tag, should be used only if you want to change the tree.\fR .IP "on_char (\s-1CODE\s0) \fI*optional\fR" 10 .IX Item "on_char (CODE) *optional" Code/sub to call on content. .Sp \&\fI** This will be called after XML::Smart parse the tag, should be used only if you want to change the tree.\fR .IP "on_end (\s-1CODE\s0) \fI*optional\fR" 10 .IX Item "on_end (CODE) *optional" Code/sub to call on end a tag. .Sp \&\fI** This will be called after XML::Smart parse the tag, should be used only if you want to change the tree.\fR .RE .RS 10 .Sp \&\fI** This options are applied when the \s-1XML\s0 data is loaded. For \s-1XML\s0 generation see \f(BIdata()\fI \s-1OPTIONS.\s0\fR .RE .PP \&\fBExamples of use:\fR .PP .Vb 1 \& my $xml_from_url = XML::Smart\->new("http://www.perlmonks.org/index.pl?node_id=16046") ; \& \& ... \& \& my $xml_from_str = XML::Smart\->new(q\` \& \& \& \& \`) ; \& \& ... \& \& my $null_xml = XML::Smart\->new() ; \& \& ... \& \& my $xml_from_html = XML::Smart\->new($html_data , \*(Aqhtml\*(Aq , \& lowtag => 1 , \& lowarg => 1 , \& on_char => sub { \& my ( $tag , $pointer , $pointer_back , $cont) = @_ ; \& $pointer\->{extra_arg} = 123 ; ## add an extrar argument. \& $pointer_back\->{$tag}{extra_arg} = 123 ; ## Same, but using the previous pointer. \& $$cont .= "\en" ; ## append data to the content. \& } \& ) ; .Ve .SS "apply_dtd (\s-1DTD , OPTIONS\s0)" .IX Subsection "apply_dtd (DTD , OPTIONS)" Apply the \fI\s-1DTD\s0\fR to the \s-1XML\s0 tree. .PP \&\fI\s-1DTD\s0\fR can be a source, file, \s-1GLOB\s0 or \s-1URL.\s0 .PP This method is useful if you need to have the \s-1XML\s0 generated by \fI\f(BIdata()\fI\fR formated in a specific \s-1DTD,\s0 so, elements will be nodes automatically, attributes will be checked, required elements and attributes will be created, the element order will be set, etc... .PP \&\fB\s-1OPTIONS:\s0\fR .IP "no_delete \s-1BOOL\s0" 10 .IX Item "no_delete BOOL" If \s-1TRUE\s0 tells that not defined elements and attributes in the \s-1DTD\s0 won't be deleted from the \s-1XML\s0 tree. .PP \&\fBExample of use:\fR .PP .Vb 10 \& $xml\->apply_dtd(q\` \& \& \& \& ]> \& \` , \& no_delete => 1 , \& ); .Ve .SS "\fBargs()\fP" .IX Subsection "args()" Return the arguments names (not nodes). .SS "\fBargs_values()\fP" .IX Subsection "args_values()" Return the arguments values (not nodes). .SS "\fBback()\fP" .IX Subsection "back()" Get back one level the pointer in the tree. .PP ** Se \fI\f(BIbase()\fI\fR. .SS "\fBbase()\fP" .IX Subsection "base()" Get back to the base of the tree. .PP Each query to the XML::Smart object return an object pointing to a different place in the tree (and share the same \s-1HASH\s0 tree). So, you can get the main object again (an object that points to the base): .PP .Vb 4 \& my $srv = $XML\->{root}{host}{server} ; \& my $addr = $srv\->{adress} ; \& my $XML2 = $srv\->base() ; \& $XML2\->{root}{hosts}... .Ve .SS "\fBcontent()\fP" .IX Subsection "content()" Return the content of a node: .PP .Vb 2 \& ## Data: \& my content \& \& ## Access: \& \& my $content = $XML\->{foo}\->content ; \& print "<<$content>>\en" ; ## show: <> \& \& ## or just: \& my $content = $XML\->{foo} ; .Ve .PP \&\fBAlso can be used with multiple contents:\fR .PP For this \s-1XML\s0 data: .PP .Vb 5 \& \& content0 \& \& content1 \& .Ve .PP Getting all the content: .PP .Vb 2 \& my $all_content = $XML\->{root}\->content ; \& print "[$all_content]\en" ; .Ve .PP Output: .PP .Vb 2 \& [ \& content0 \& \& content1 \& ] .Ve .PP Getting in parts: .PP .Vb 3 \& my @contents = $XML\->{root}\->content ; \& print "[@contents[0]]\en" ; \& print "[@contents[1]]\en" ; .Ve .PP Output .PP .Vb 6 \& [ \& content0 \& ] \& [ \& content1 \& ] .Ve .PP \&\fBSetting multiple contents:\fR .PP .Vb 2 \& $XML\->{root}\->content(0,"aaaaa") ; \& $XML\->{root}\->content(1,"bbbbb") ; .Ve .PP Output now will be: .PP .Vb 2 \& [aaaaa] \& [bbbbb] .Ve .PP And now the \s-1XML\s0 data generated will be: .PP .Vb 1 \& aaaaabbbbb .Ve .SS "\fBcopy()\fP" .IX Subsection "copy()" Return a copy of the XML::Smart object (pointing to the base). .PP ** This is good when you want to keep 2 versions of the same \s-1XML\s0 tree in the memory, since one object can't change the tree of the other! .PP \&\fB\s-1WARNING:\s0\fR \fBset_node()\fR, \fBset_cdata()\fR and \fBset_binary()\fR changes are not persistent over copy \- Once you create a second copy these states are lost. .PP b do not copy after \fBapply_dtd()\fR unless you have checked for dtd errors. .SS "\fBcut_root()\fP" .IX Subsection "cut_root()" Cut the root key: .PP .Vb 1 \& my $srv = $XML\->{rootx}{host}{server} ; \& \& ## Or if you don\*(Aqt know the root name: \& $XML = $XML\->cut_root() ; \& my $srv = $XML\->{host}{server} ; .Ve .PP ** Note that this will cut the root of the pointer in the tree. So, if you are in some place that have more than one key (multiple roots), the same object will be retuned without cut anything. .SS "data (\s-1OPTIONS\s0)" .IX Subsection "data (OPTIONS)" Return the data of the \s-1XML\s0 object (rebuilding it). .PP \&\fBOptions:\fR .IP "nodtd" 11 .IX Item "nodtd" Do not add in the \s-1XML\s0 content the \s-1DTD\s0 applied by the method \fI\f(BIapply_dtd()\fI\fR. .IP "noident" 11 .IX Item "noident" If set to true the data isn't idented. .IP "nospace" 11 .IX Item "nospace" If set to true the data isn't idented and doesn't have space between the tags (unless the \s-1CONTENT\s0 have). .IP "lowtag" 11 .IX Item "lowtag" Make the tags lower case. .IP "lowarg" 11 .IX Item "lowarg" Make the arguments lower case. .IP "upertag" 11 .IX Item "upertag" Make the tags uper case. .IP "uperarg" 11 .IX Item "uperarg" Make the arguments uper case. .IP "length" 11 .IX Item "length" If set true, add the attribute 'length' with the size of the data to the xml header (). This is useful when you send the data through a socket, since the socket can know the total amount of data to read. .IP "noheader" 11 .IX Item "noheader" Do not add the header. .IP "nometagen" 11 .IX Item "nometagen" Do not add the meta generator tag: .IP "meta" 11 .IX Item "meta" Set the meta tags of the \s-1XML\s0 document. .IP "decode" 11 .IX Item "decode" As of \s-1VERSION 1.73\s0 there are three different base64 encodings that are used. They are picked based on which of them support the data provided. If you want to retrieve data using the 'data' function the resultant xml will have dt:dt=\*(L"binary.based\*(R" contained within it. To retrieve the decoded data use: \f(CW$XML\fR\->data( decode => 1 ) .Sp Examples: .Sp .Vb 4 \& my $meta = { \& build_from => "wxWindows 2.4.0" , \& file => "wx26.htm" , \& } ; \& \& print $XML\->data( meta => $meta ) ; \& \& _\|_DATA_\|_ \& .Ve .Sp Multiple meta: .Sp .Vb 4 \& my $meta = [ \& {build_from => "wxWindows 2.4.0" , file => "wx26.htm" } , \& {script => "genxml.pl" , ver => "1.0" } , \& ] ; \& \& _\|_DATA_\|_ \& \& .Ve .Sp Or set directly the meta tag: .Sp .Vb 1 \& my $meta = \*(Aq\*(Aq ; \& \& ## For multiple: \& my $meta = [\*(Aq\*(Aq , \*(Aq\*(Aq] ; \& \& print $XML\->data( meta => $meta ) ; .Ve .IP "tree" 11 .IX Item "tree" Set the \s-1HASH\s0 tree to parse. If not set will use the tree of the XML::Smart object (\fI\f(BItree()\fI\fR). ; .IP "wild" 11 .IX Item "wild" Accept wild tags and arguments. .Sp ** This wont fix wrong keys and tags. .IP "sortall" 11 .IX Item "sortall" Sort all the tags alphabetically. If not set will keep the order of the document loaded, or the order of tag creation. \&\fIDefault:\fR off .SS "data_pointer (\s-1OPTIONS\s0)" .IX Subsection "data_pointer (OPTIONS)" Make the tree from current point in the \s-1XML\s0 tree (not from the base as \fBdata()\fR). .PP Accept the same \s-1OPTIONS\s0 of the method \fB\f(BI\f(BIdata()\f(BI\fB\fR. .SS "\fBdump_tree()\fP" .IX Subsection "dump_tree()" Dump the tree of the object using Data::Dumper. .SS "\fBdump_tree_pointer()\fP" .IX Subsection "dump_tree_pointer()" Dump the tree of the object, from the pointer, using Data::Dumper. .SS "\fBdump_pointer()\fP" .IX Subsection "dump_pointer()" \&\fI** Same as \f(BIdump_tree_pointer()\fI\fR. .SS "i()" .IX Subsection "i()" Return the index of the value. .PP ** If the value is from an hash key (not an \s-1ARRAY\s0 ref) undef is returned. .SS "\fBis_node()\fP" .IX Subsection "is_node()" Return if a key is a node. .SS "\fBkey()\fP" .IX Subsection "key()" Return the key of the value. .PP If wantarray return the index too: return(\s-1KEY , I\s0) ; .SS "\fBnodes()\fP" .IX Subsection "nodes()" Return the nodes (objects) in the pointer (keys that aren't arguments). .SS "\fBnodes_keys()\fP" .IX Subsection "nodes_keys()" Return the nodes names (not the object) in the pointer (keys that aren't arguments). .SS "\fBnull()\fP" .IX Subsection "null()" Return \fItrue\fR if the \s-1XML\s0 object has a null tree or if the pointer is in some place that doesn't exist. .SS "\fBorder()\fP" .IX Subsection "order()" Return the order of the keys. See \fI\f(BIset_order()\fI\fR. .SS "\fBpath()\fP" .IX Subsection "path()" Return the path of the pointer. .PP \&\fIExample\fR: .PP .Vb 1 \& /hosts/server[1]/address[0] .Ve .PP \&\fBNote that the index is 0 based and 'address' can be an attribute or a node, what is not compatible with XPath.\fR .PP \&\fB** See \f(BI\f(BIpath_as_xpath()\f(BI\fB.\fR .SS "\fBpath_as_xpath()\fP" .IX Subsection "path_as_xpath()" Return the path of the pointer in the XPath format. .SS "pointer" .IX Subsection "pointer" Return the \s-1HASH\s0 tree from the pointer. .SS "pointer_ok" .IX Subsection "pointer_ok" Return a copy of the tree of the object, \fBfrom the pointer\fR, but without internal keys added by \fIXML::Smart\fR. .SS "root" .IX Subsection "root" Return the \s-1ROOT\s0 name of the \s-1XML\s0 tree (main key). .PP ** See also \fI\f(BIkey()\fI\fR for sub nodes. .SS "save (\s-1FILEPATH , OPTIONS\s0)" .IX Subsection "save (FILEPATH , OPTIONS)" Save the \s-1XML\s0 data inside a file. .PP Accept the same \s-1OPTIONS\s0 of the method \fB\f(BI\f(BIdata()\f(BI\fB\fR. .SS "set_auto" .IX Subsection "set_auto" Define the key to be handled automatically. Soo, \fBdata()\fR will define automatically if it's a node, content or attribute. .PP \&\fI** This method is useful to remove \f(BIset_node()\fI, \f(BIset_cdata()\fI and \f(BIset_binary()\fI changes.\fR .SS "set_auto_node" .IX Subsection "set_auto_node" Define the key as a node, and \fBdata()\fR will define automatically if it's \s-1CDATA\s0 or \s-1BINARY.\s0 .PP \&\fI** This method is useful to remove \f(BIset_cdata()\fI and \f(BIset_binary()\fI changes.\fR .SS "set_binary(\s-1BOOL\s0)" .IX Subsection "set_binary(BOOL)" Define the node as a \s-1BINARY\s0 content when \s-1TRUE,\s0 or force to \fBnot\fR handle it as a \s-1BINARY\s0 on \s-1FALSE.\s0 .PP Example of node handled as \s-1BINARY:\s0 .PP .Vb 1 \& PGgxPnRlc3QgAzwvaDE+ .Ve .PP Original content of foo (the base64 data): .PP .Vb 1 \&

test \ex03

.Ve .SS "set_cdata(\s-1BOOL\s0)" .IX Subsection "set_cdata(BOOL)" Define the node as \s-1CDATA\s0 when \s-1TRUE,\s0 or force to \fBnot\fR handle it as \s-1CDATA\s0 on \s-1FALSE.\s0 .PP Example of \s-1CDATA\s0 node: .PP .Vb 1 \& bla bla]]> .Ve .SS "set_node(\s-1BOOL\s0)" .IX Subsection "set_node(BOOL)" Set/unset the current key as a node (tag). .PP ** If \s-1BOOL\s0 is not defined will use \fI\s-1TRUE\s0\fR. .PP \&\fB\s-1WARNING:\s0\fR You cannot set_node, copy the object and then set_node( 0 ) [ Unset node ] .SS "set_order(\s-1KEYS\s0)" .IX Subsection "set_order(KEYS)" Set the order of the keys (nodes and attributes) in this point. .SS "set_tag" .IX Subsection "set_tag" Same as set_node. .SS "\fBtree()\fP" .IX Subsection "tree()" Return the \s-1HASH\s0 tree of the \s-1XML\s0 data. .PP ** Note that the real \s-1HASH\s0 tree is returned here. All the other ways return an object that works like a \s-1HASH/ARRAY\s0 through tie. .SS "\fBtree_pointer()\fP" .IX Subsection "tree_pointer()" Same as \fI\f(BIpointer()\fI\fR. .SS "\fBtree_ok()\fP" .IX Subsection "tree_ok()" Return a copy of the tree of the object, but without internal keys added by \fIXML::Smart\fR, like \fI/order\fR and \fI/nodes\fR. .SS "\fBtree_pointer_ok()\fP" .IX Subsection "tree_pointer_ok()" Return a copy of the tree of the object, \fBfrom the pointer\fR, but without internal keys added by \fIXML::Smart\fR. .SS "\fBxpath()\fP || \fBXPath()\fP" .IX Subsection "xpath() || XPath()" Return a XML::XPath object, based in the \s-1XML\s0 root in the tree. .PP .Vb 2 \& ## look from the root: \& my $data = $XML\->XPath\->findnodes_as_string(\*(Aq/\*(Aq) ; .Ve .PP \&\fI** Need XML::XPath installed, but only load when is needed.\fR .SS "\fBxpath_pointer()\fP || \fBXPath_pointer()\fP" .IX Subsection "xpath_pointer() || XPath_pointer()" Return a XML::XPath object, based in the XML::Smart pointer in the tree. .PP .Vb 1 \& ## look from this point, soo XPath \*(Aq/\*(Aq actually starts at /server/: \& \& my $srvs = $XML\->{server} ; \& my $data = $srvs\->XPath_pointer\->findnodes_as_string(\*(Aq/\*(Aq) ; .Ve .PP \&\fI** Need XML::XPath installed, but only load when is needed.\fR .SS "\s-1ANNIHILATE\s0" .IX Subsection "ANNIHILATE" XML::Smart uses XML::XPath that, for perfomance reasons, leaks memory. The ensure that this memory is freed you can explicitly call \s-1ANNIHILATE\s0 before the XML::Smart object goes out of scope. .SH "ACCESS" .IX Header "ACCESS" To access the data you use the object in a way similar to \s-1HASH\s0 and \s-1ARRAY:\s0 .PP .Vb 1 \& my $XML = XML::Smart\->new(\*(Aqfile.xml\*(Aq) ; \& \& my $server = $XML\->{server} ; .Ve .PP But when you get a key {server}, you are actually accessing the data through \fBtie()\fR, not directly to the \s-1HASH\s0 tree inside the object, (This will fix wrong accesses): .PP .Vb 1 \& ## {server} is a normal key, not an ARRAY ref: \& \& my $server = $XML\->{server}[0] ; ## return $XML\->{server} \& my $server = $XML\->{server}[1] ; ## return UNDEF \& \& ## {server} has an ARRAY with 2 items: \& \& my $server = $XML\->{server} ; ## return $XML\->{server}[0] \& my $server = $XML\->{server}[0] ; ## return $XML\->{server}[0] \& my $server = $XML\->{server}[1] ; ## return $XML\->{server}[1] .Ve .PP To get all the values of multiple elements/keys: .PP .Vb 2 \& ## This work having only a string inside {address}, or with an ARRAY ref: \& my @addrsses = @{$XML\->{server}{address}} ; .Ve .SS "Select search" .IX Subsection "Select search" When you don't know the position of the nodes, you can select it by some attribute value: .PP .Vb 1 \& my $server = $XML\->{server}(\*(Aqtype\*(Aq,\*(Aqeq\*(Aq,\*(Aqsuse\*(Aq) ; ## return $XML\->{server}[1] .Ve .PP Syntax for the select search: .PP .Vb 1 \& (NAME, CONDITION , VALUE) .Ve .IP "\s-1NAME\s0" 10 .IX Item "NAME" The attribute name in the node (tag). .IP "\s-1CONDITION\s0" 10 .IX Item "CONDITION" Can be .Sp .Vb 1 \& eq ne == != <= >= < > .Ve .Sp For \s-1REGEX:\s0 .Sp .Vb 1 \& =~ !~ \& \& ## Case insensitive: \& =~i !~i .Ve .IP "\s-1VALUE\s0" 10 .IX Item "VALUE" The value. .Sp For \s-1REGEX\s0 use like this: .Sp .Vb 1 \& $XML\->{server}(\*(Aqtype\*(Aq,\*(Aq=~\*(Aq,\*(Aq^s\ew+$\*(Aq) ; .Ve .SS "Select attributes in multiple nodes:" .IX Subsection "Select attributes in multiple nodes:" You can get the list of values of an attribute looking in all multiple nodes: .PP .Vb 2 \& ## Get all the server types: \& my @types = $XML\->{server}(\*(Aq[@]\*(Aq,\*(Aqtype\*(Aq) ; .Ve .PP Also as: .PP .Vb 1 \& my @types = $XML\->{server}{type}(\*(Aq<@\*(Aq) ; .Ve .PP Without the resource: .PP .Vb 2 \& my @list ; \& my @servers = @{$XML\->{server}} ; \& \& foreach my $servers_i ( @servers ) { \& push(@list , $servers_i\->{type} ) ; \& } .Ve .SS "Return format" .IX Subsection "Return format" You can change the returned format: .PP Syntax: .PP .Vb 1 \& (TYPE) .Ve .PP Where \s-1TYPE\s0 can be: .PP .Vb 4 \& $ ## the content. \& @ ## an array (list of multiple values). \& % ## a hash. \& . ## The exact point in the tree, not an object. \& \& $@ ## an array, but with the content, not an objects. \& $% ## a hash, but the values are the content, not an object. \& \& ## The use of $@ and $% is good if you don\*(Aqt want to keep the object \& ## reference (and save memory). \& \& @keys ## The keys of the node. note that if you have a key with \& ## multiple nodes, it will be replicated (this is the \& ## difference of "keys %{$this\->{node}}" ). \& \& <@ ## Return the attribute in the previous node, but looking for \& ## multiple nodes. Example: \& \& my @names = $this\->{method}{wxFrame}{arg}{name}(\*(Aq<@\*(Aq) ; \& #### @names = (parent , id , title) ; \& \& ## Return a XML data from this point. \& \& _\|_DATA_\|_ \& \& \& \& \& \& \& .Ve .PP Example: .PP .Vb 7 \& ## A servers content \& my $name = $XML\->{server}{name}(\*(Aq$\*(Aq) ; \& ## ... or: \& my $name = $XML\->{server}{name}\->content ; \& ## ... or: \& my $name = $XML\->{server}{name} ; \& $name = "$name" ; \& \& ## All the servers \& my @servers = $XML\->{server}(\*(Aq@\*(Aq) ; \& ## ... or: \& my @servers = @{$XML\->{server}} ; \& \& ## It still has the object reference: \& @servers[0]\->{name} ; \& \& ## Without the reference: \& my @servers = $XML\->{server}(\*(Aq$@\*(Aq) ; \& \& ## A XML data, same as data_pointer(): \& my $xml_data = $XML\->{server}(\*(Aq\*(Aq) ; .Ve .SS "\s-1CONTENT\s0" .IX Subsection "CONTENT" If a {key} has a content you can access it directly from the variable or from the method: .PP .Vb 1 \& my $server = $XML\->{server} ; \& \& print "Content: $server\en" ; \& ## ...or... \& print "Content: ". $server\->content ."\en" ; .Ve .PP So, if you use the object as a string it works as a string, if you use as an object it works as an object! ;\-P .PP \&\fI**See the method \f(BIcontent()\fI for more.\fR .SH "CREATING XML DATA" .IX Header "CREATING XML DATA" To create \s-1XML\s0 data is easy, you just use as a normal \s-1HASH,\s0 but you don't need to care with multiple nodes, and \s-1ARRAY\s0 creation/convertion! .PP .Vb 2 \& ## Create a null XML object: \& my $XML = XML::Smart\->new() ; \& \& ## Add a server to the list: \& $XML\->{server} = { \& os => \*(AqLinux\*(Aq , \& type => \*(Aqmandrake\*(Aq , \& version => 8.9 , \& address => \*(Aq192.168.3.201\*(Aq , \& } ; \& \& ## The data now: \& \& \& ## Add a new address to the server. Have an ARRAY creation, convertion \& ## of the previous key to ARRAY: \& $XML\->{server}{address}[1] = \*(Aq192.168.3.202\*(Aq ; \& \& ## The data now: \& \&
192.168.3.201
\&
192.168.3.202
\&
.Ve .PP After create your \s-1XML\s0 tree you just save it or get the data: .PP .Vb 2 \& ## Get the data: \& my $data = $XML\->data ; \& \& ## Or save it directly: \& $XML\->save(\*(Aqnewfile.xml\*(Aq) ; \& \& ## Or send to a socket: \& print $socket $XML\->data(length => 1) ; .Ve .SH "BINARY DATA & CDATA" .IX Header "BINARY DATA & CDATA" From version 1.2 \fIXML::Smart\fR can handle binary data and \s-1CDATA\s0 blocks automatically. .PP \&\fBWhen parsing\fR, binary data will be detected as: .PP .Vb 1 \& f1NPTUUgQklOQVJZIERBVEE= .Ve .PP \&\fISince this is the oficial automatically format for binary data at \s-1XML\s0.com .\fR The content will be decoded from base64 and saved in the object tree. .PP \&\s-1CDATA\s0 will be parsed as any other content, since \s-1CDATA\s0 is only a block that won't be parsed. .PP \&\fBWhen creating \s-1XML\s0 data\fR, like at \f(CW$XML\fR\->\fBdata()\fR, the binary format and \s-1CDATA\s0 are detected using these rules: .PP .Vb 2 \& BINARY: \& \- If your data has characters that can\*(Aqt be in XML. \& \& * Characters accepted: \& \& \es \ew \ed \& !"#$%&\*(Aq()*+,\-./:;<=>?@[\e]^\`{|}~ \& 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8e, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, \& 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9e, 0x9f, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, \& 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, \& 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, \& 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, \& 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, \& 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x20 \& \& TODO: 0x80, 0x81, 0x8d, 0x8f, 0x90, 0xa0 \& \& CDATA: \& \- If have tags: <...> \& \& CONTENT: (content) \& \- If have \er\en\et, or \*(Aq and " at the same time. .Ve .PP So, this will be a \s-1CDATA\s0 content: .PP .Vb 5 \& \& line2 \& ]]> .Ve .PP If binary content is detected, it will be converted to \fBbase64\fR and a \fBdt:dt\fR attribute added in the tag to tell the format. .PP .Vb 1 \& f1NPTUUgQklOQVJZIERBVEE= .Ve .PP \&\fB\s-1NOTE:\s0\fR As of \s-1VERSION 1.73\s0 there are three different base64 encodings that are used. They are picked based on which of them support the data provided. If you want to retrieve data using the 'data' function the resultant xml will have dt:dt=\*(L"binary.based\*(R" contained within it. To retrieve the decoded data use: \f(CW$XML\fR\->data( decode => 1 ) .SH "UNICODE and ASCII-extended (ISO\-8859\-1)" .IX Header "UNICODE and ASCII-extended (ISO-8859-1)" \&\fIXML::Smart\fR support only thse 2 encode types, Unicode (\s-1UTF\-8\s0) and ASCII-extended (\s-1ISO\-8859\-1\s0), and must be enough. (\fBNote that \s-1UTF\-8\s0 is only supported on Perl\-5.8+\fR). .PP When creating \s-1XML\s0 data, if any \s-1UTF\-8\s0 character is detected the \fIencoding\fR attribute in the header will be set to \s-1UTF\-8:\s0 .PP .Vb 2 \& \& 0x82, 0x83 .Ve .PP If not, the \fIiso\-8859\-1\fR is used: .PP .Vb 2 \& \& 0x82 .Ve .PP When loading \s-1XML\s0 data with \s-1UTF\-8,\s0 Perl (5.8+) should make all the work internally. .SH "PARSING HTML as XML, or BAD XML formats" .IX Header "PARSING HTML as XML, or BAD XML formats" You can use the special parser \fBXML::Smart::HTMLParser\fR to \*(L"use\*(R" \s-1HTML\s0 as \s-1XML\s0 or not well-formed \s-1XML\s0 data. .PP The differences between an normal \s-1XML\s0 parser and \fIXML::Smart::HTMLParser\fR are: .PP .Vb 2 \& \- Accept values without quotes: \& \& \& \- Accept any data in the values, including <> and &: \& out.txt"> \& \& \- Accpet URI values without quotes: \& \& \& \- Don\*(Aqt need to close the tags adding the \*(Aq/\*(Aq before \*(Aq>\*(Aq: \& \& \& ** Note that the parse will try hard to detect the nodes, and where \& auto\-close or not. \& \& \- Don\*(Aqt need to have only one root: \& datadata .Ve .PP So, \fIXML::Smart::HTMLParser\fR is a willd way to load markuped data (like \s-1HTML\s0), or if you don't want to care with quotes, end tags, etc... when writing by hand your \s-1XML\s0 data. So, you can write by hand a bad \s-1XML\s0 file, load it with \fIXML::Smart::HTMLParser\fR, and \fBrewrite well\fR saving it again! ;\-P .PP ** Note that <\s-1SCRIPT\s0> tags will only parse right if the content is inside comments , since they can have tags: .PP .Vb 3 \& .Ve .SH "ENTITIES" .IX Header "ENTITIES" Entities (\s-1ENTITY\s0) are handled by the parser. So, if you use XML::Parser it will do all the job fine. But If you use \fIXML::Smart::Parser\fR or \fIXML::Smart::HMLParser\fR, only the basic entities (defaults) will be parsed: .PP .Vb 5 \& < => The less than sign (<). \& > => The greater than sign (>). \& & => The ampersand (&). \& ' => The single quote or apostrophe (\*(Aq). \& " => The double quote ("). \& \& &#ddd; => An ASCII character or an Unicode character (>255). Where ddd is a decimal. \& &#xHHH; => An Unicode character. Where HHH is in hexadecimal. .Ve .PP \&\fBWhen creating \s-1XML\s0 data\fR, already existent Entities won't be changed, and the characters '<', '&' and '>' will be converted to the appropriated entity. .PP ** Note that if a content have a , the characters '<' and '>' won't be converted to entities, and this content will be inside a \s-1CDATA\s0 block. .SH "WHY AND HOW IT WORKS" .IX Header "WHY AND HOW IT WORKS" Every one that have tried to use Perl \s-1HASH\s0 and \s-1ARRAY\s0 to access \s-1XML\s0 data, like in XML::Simple, have some problems to add new nodes, or to access the node when the user doesn't know if it's inside an \s-1ARRAY,\s0 a \s-1HASH\s0 or a \s-1HASH\s0 key. \fIXML::Smart\fR create around it a very dynamic way to access the data, since at the same time any node/point in the tree can be a \s-1HASH\s0 and an \s-1ARRAY.\s0 You also have other extra resources, like a search for nodes by attribute: .PP .Vb 1 \& my $server = $XML\->{server}(\*(Aqtype\*(Aq,\*(Aqeq\*(Aq,\*(Aqsuse\*(Aq) ; ## This syntax is not wrong! ;\-) \& \& ## Instead of: \& my $server = $XML\->{server}[1] ; \& \& _\|_DATA_\|_ \& \& \& \& .Ve .PP The idea for this module, came from the problem that exists to access a complex struture in \s-1XML.\s0 You just need to know how is this structure, something that is generally made looking the \s-1XML\s0 file (what is wrong). But at the same time is hard to always check (by code) the struture, before access it. \&\s-1XML\s0 is a good and easy format to declare your data, but to extrac it in a tree way, at least in my opinion, isn't easy. To fix that, came to my mind a way to access the data with some query language, like \s-1SQL.\s0 The first idea was to access using something like: .PP .Vb 1 \& XML.foo.bar.baz{arg1} \& \& X = XML.foo.bar* \& X.baz{arg1} \& \& XML.hosts.server[0]{argx} .Ve .PP And saw that this is very similar to Hashes and Arrays in Perl: .PP .Vb 1 \& $XML\->{foo}{bar}{baz}{arg1} ; \& \& $X = $XML\->{foo}{bar} ; \& $X\->{baz}{arg1} ; \& \& $XML\->{hosts}{server}[0]{argx} ; .Ve .PP But the problem of Hash and Array, is not knowing when you have an Array reference or not. For example, in XML::Simple: .PP .Vb 4 \& ## This is very diffenrent \& $XML\->{server}{address} ; \& ## ... of this: \& $XML\->{server}{address}[0] ; .Ve .PP So, why don't make both ways work? Because you need to make something crazy! .PP To create \fIXML::Smart\fR, first I have created the module Object::MultiType. With it you can have an object that works at the same time as a \s-1HASH, ARRAY, SCALAR, CODE & GLOB.\s0 So you can do things like this with the same object: .PP .Vb 1 \& $obj = Object::MultiType\->new() ; \& \& $obj\->{key} ; \& $obj\->[0] ; \& $obj\->method ; \& \& @l = @{$obj} ; \& %h = %{$obj} ; \& \& &$obj(args) ; \& \& print $obj "send data\en" ; .Ve .PP Seems to be crazy, and can be more if you use \fBtie()\fR inside it, and this is what \fIXML::Smart\fR does. .PP For \fIXML::Smart\fR, the access in the Hash and Array way paste through \fBtie()\fR. In other words, you have a tied \s-1HASH\s0 and tied \s-1ARRAY\s0 inside it. This tied Hash and Array work together, soo \fByou can access a Hash key as the index 0 of an Array, or access an index 0 as the Hash key\fR: .PP .Vb 3 \& %hash = ( \& key => [\*(Aqa\*(Aq,\*(Aqb\*(Aq,\*(Aqc\*(Aq] \& ) ; \& \& $hash\->{key} ## return $hash{key}[0] \& $hash\->{key}[0] ## return $hash{key}[0] \& $hash\->{key}[1] ## return $hash{key}[1] \& \& ## Inverse: \& \& %hash = ( key => \*(Aqa\*(Aq ) ; \& \& $hash\->{key} ## return $hash{key} \& $hash\->{key}[0] ## return $hash{key} \& $hash\->{key}[1] ## return undef .Ve .PP The best thing of this new resource is to avoid wrong access to the data and warnings when you try to access a Hash having an Array (and the inverse). Thing that generally make the script \fBdie()\fR. .PP Once having an easy access to the data, you can use the same resource to \fBcreate\fR data! For example: .PP .Vb 4 \& ## Previous data: \& \& \& \& \& ## Now you have {address} as a normal key with a string inside: \& $XML\->{hosts}{server}{address} \& \& ## And to add a new address, the key {address} need to be an ARRAY ref! \& ## So, XML::Smart make the convertion: ;\-P \& $XML\->{hosts}{server}{address}[1] = \*(Aq192.168.2.101\*(Aq ; \& \& ## Adding to a list that you don\*(Aqt know the size: \& push(@{$XML\->{hosts}{server}{address}} , \*(Aq192.168.2.102\*(Aq) ; \& \& ## The data now: \& \& \&
192.168.2.100
\&
192.168.2.101
\&
192.168.2.102
\&
\&
.Ve .PP Than after changing your \s-1XML\s0 tree using the Hash and Array resources you just get the data remade (through the Hash tree inside the object): .PP .Vb 1 \& my $xmldata = $XML\->data ; .Ve .PP \&\fBBut note that \f(BIXML::Smart\fB always return an object\fR! Even when you get a final key. So this actually returns another object, pointhing (inside it) to the key: .PP .Vb 1 \& $addr = $XML\->{hosts}{server}{address}[0] ; \& \& ## Since $addr is an object you can TRY to access more data: \& $addr\->{foo}{bar} ; ## This doens\*(Aqt make warnings! just return UNDEF. \& \& ## But you can use it like a normal SCALAR too: \& \& print "$addr\en" ; \& \& $addr .= \*(Aq:80\*(Aq ; ## After this $addr isn\*(Aqt an object any more, just a SCALAR! .Ve .SH "TODO" .IX Header "TODO" .Vb 5 \& * Finish XPath implementation. \& * DTD \- Handle gracefully. \& * Implement a better way to declare meta tags. \& * Add 0x80, 0x81, 0x8d, 0x8f, 0x90, 0xa0 ( multi byte characters to the list of accepted binary characters ) \& * Ensure object copy holds more in state including: \->data( wild => 1 ) .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" XML::Parser, XML::Parser::Lite, XML::XPath, \s-1XML\s0. .PP Object::MultiType \- This is the module that make everything possible, and was created specially for \fIXML::Smart\fR. ;\-P .PP ** See the test.pl script for examples of use. .PP \&\s-1XML\s0.com .SH "AUTHOR" .IX Header "AUTHOR" Graciliano M. P. \f(CW\*(C`\*(C'\fR .PP I will appreciate any type of feedback (include your opinions and/or suggestions). ;\-P .PP Enjoy and thanks for who are enjoying this tool and have sent e\-mails! ;\-P .SH "CURRENT MAINTAINER" .IX Header "CURRENT MAINTAINER" Harish Madabushi, \f(CW\*(C`\*(C'\fR .SH "BUGS" .IX Header "BUGS" Please report any bugs or feature requests to \f(CW\*(C`bug\-xml\-smart at rt.cpan.org\*(C'\fR, or through the web interface at . Both the author and the maintainer will be notified, and then you'll automatically be notified of progress on your bug as changes are made. .SH "SUPPORT" .IX Header "SUPPORT" You can find documentation for this module with the perldoc command. .PP .Vb 1 \& perldoc XML::Smart .Ve .PP You can also look for information at: .IP "\(bu" 5 \&\s-1RT: CPAN\s0's request tracker (report bugs here) .Sp .IP "\(bu" 5 AnnoCPAN: Annotated \s-1CPAN\s0 documentation .Sp .IP "\(bu" 5 \&\s-1CPAN\s0 Ratings .Sp .IP "\(bu" 5 Search \s-1CPAN\s0 .Sp .IP "\(bu" 5 GitHub \s-1CPAN\s0 .Sp .SH "THANKS" .IX Header "THANKS" Thanks to Rusty Allen for the extensive tests of \s-1CDATA\s0 and \s-1BINARY\s0 handling of XML::Smart. .PP Thanks to Ted Haining to point a Perl\-5.8.0 bug for tied keys of a \s-1HASH.\s0 .PP Thanks to everybody that have sent ideas, patches or pointed bugs. .SH "LICENSE AND COPYRIGHT" .IX Header "LICENSE AND COPYRIGHT" Copyright 2003 Graciliano M. P. .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.