NAME
XML::TreePP::XMLPath - Something similar to XPath, allowing definition of paths to XML subtrees
SYNOPSIS
use XML::TreePP;
use XML::TreePP::XMLPath;
my $tpp = XML::TreePP->new();
my $tppx = XML::TreePP::XMLPath->new();
my $tree = { rss => { channel => { item => [ {
title => "The Perl Directory",
link => "http://www.perl.org/",
}, {
title => "The Comprehensive Perl Archive Network",
link => "http://cpan.perl.org/",
} ] } } };
my $xml = $tpp->write( $tree );
Get a subtree of the XMLTree:
my $xmlsub = $tppx->getSubTree( $xml , q{rss/channel/item[title="The Comprehensive Perl Archive Network"]} );
print $xmlsub->{'link'};
Iterate through all attributes and Elements of each <item> XML element:
my $xmlsub = $tppx->getSubTree( $xml , q{rss/channel/item} );
my $h_attr = $tppx->getAttributes( $xmlsub );
my $h_elem = $tppx->getElements( $xmlsub );
foreach $attrHash ( @{ $h_attr } ) {
while my ( $attrKey, $attrVal ) = each ( %{$attrHash} ) {
...
}
}
foreach $elemHash ( @{ $h_elem } ) {
while my ( $elemName, $elemVal ) = each ( %{$elemHash} ) {
...
}
}
DESCRIPTION
A Pure PERL extension to Pure PERL XML::TreePP module to support paths to XML subtree content. This may seem similar to XPath, but it is not XPath.
REQUIREMENTS
The following perl modules are depended on by this module: ( Note: Dependency on Params::Validate was removed in version 0.52 )
XML::TreePP
IMPORTABLE METHODS
When the calling application invokes this module in a use clause, the following methods can be imported into its space.
filterXMLDoc
getAttributes
getElements
getSubtree
parseXMLPath
Example:
use XML::TreePP::XMLPath qw(parseXMLPath filterXMLDoc getAttributes getElements getSubtree);
XMLPath PHILOSOPHY
Referring to the following XML Data.
<paragraph>
<sentence language="english">
<words>Do red cats eat yellow food</words>
<punctuation>?</punctuation>
</sentence>
<sentence language="english">
<words>Brown cows eat green grass</words>
<punctuation>.</punctuation>
</sentence>
</paragraph>
Where the path "paragraph/sentence[@language=english]/words
" has two matches: "Do red cats eat yellow food
" and "Brown cows eat green grass
".
Where the path "paragraph/sentence[@language]
" has the same previous two matches.
Where the path "paragraph/sentence[2][@language=english]/words
" has one match: "Brown cows eat green grass
".
And where the path "paragraph/sentence[punctuation=.]/words
" matches "Brown cows eat green grass
"
So that "[@attr=val]
" is identified as an attribute inside the "<tag attr='val'></tag>"
And "[attr=val]
" is identified as a nested attribute inside the "<tag><attr>val</attr></tag>"
And "[2]
" is a positional argument identifying the second node in a list "<tag><attr>value-1</attr><attr>value-2</attr></tag>".
And "@attr
" identifies all nodes containing the @attr
attribute. "<tag><item attr="value-A">value-1</item><item attr="value-B">value-2</item></tag>".
After XML::TreePP parses the above XML, it looks like this:
{
paragraph => {
sentence => [
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
},
{
"-language" => "english",
punctuation => ".",
words => "Brown cows eat green grass",
},
],
},
}
Things To Note
Note that attributes are specified in the XMLPath as @attribute_name
, but after XML::TreePP::parse()
parses the XML Document, the attribute name is identifed as -attribute_name
in the resulting parsed document. As of version 0.52 this can be changed using the set(attr_prefix=
'@')> method. It should only be changed if the XML Docuement is provided as already parsed, and the attributes are represented with a value other than the default. This document uses the default value of -
in its examples.
XMLPath requires attributes to be specified as @attribute_name
and takes care of the conversion from @
to -
behind the scenes when accessing the XML::TreePP parsed XML document.
Child elements on the next level of a parent element are accessible as attributes as attribute_name
. This is the same format as @attribute_name
except without the @
symbol. Specifying the attribute without an @
symbol identifies the attribute as a child element of the parent element being evaluated.
Child element values are only accessible as CDATA
. That is when the element being evaluated is animal
, the attribute (or child element) is cat
, and the value of the attribute is tiger
, it is presented as this:
<jungle>
<animal>
<cat>tiger</cat>
</animal>
</jungle>
The XMLPath used to access the key=value pair of cat=tiger
for element animal
would be as follows:
jungle/animal[cat='tiger']
And in version 0.52, in this second case, the above XMLPath is still valid:
<jungle>
<animal>
<cat color="black">tiger</cat>
</animal>
</jungle>
In version 0.52, the period (.) is supported as it is in XPath to represent the current context node. As such, the following XMLPaths would also be valid:
jungle/animal/cat[.='tiger']
jungle/animal/cat[@color='black'][.='tiger']
One should realize that in these previous two XMLPaths, the element cat
is being evaluated, and not the element animal
as in the first case. And will be undesireable if you want to evaluate animal
for results.
To perform the same evaluation, but return the matching animal
node, the following XMLPath can be used:
jungle/animal[cat='tiger']
To evaluate animal
and cat
, but return the matching cat
node, the following XMLPaths can be used:
jungle/animal[cat='tiger']/cat
jungle/animal/cat[.='tiger']
The first path analizes animal
, and the second path analizes cat
. But both matches the same node "<cat color='black>tiger</cat>".
Matching attributes
Prior to version 0.52, attributes could only be used in XMLPath to evaluate an element for a result set. As of version 0.52, attributes can now be matched in XMLPath to return their values.
This next example illustrates:
<jungle>
<animal>
<cat color="black">tiger</cat>
</animal>
</jungle>
/jungle/animal/cat[.='tiger']/@color
The result set of this XMLPath would be "black
".
METHODS
tpp
This module is an extension of the XML::TreePP module. As such, it uses the module in many different methods to parse XML Docuements, and when the user calls the set()
and get()
methods to set and get properties specific to the module.
The XML::TreePP module, however, is only loaded into XML::TreePP::XMLPath when it becomes necessary to perform the previously described requests.
To avoid having this module load the XML::TreePP module, the caller must be sure to avoid the following:
1. Do not call the set()
and get()
methods to set or get properties specific to XML::TreePP. Doing so will cause this module to load XML::TreePP in order to set or get those properties. In turn, that loaded instance of XML::TreePP is used internally when needed in the future.
2. Do not pass in unparsed XML Documents. The caller would instead want to parse the XML Document with XML::TreePP::parse()
before passing it in. Passing in an unparsed XML document causes this module to load XML::TreePP
in order to parse it for processing.
Alternaltely, If the caller has loaded a copy of XML::TreePP, that instance can be assigned to be used by the instance of this module using this method. In doing so, when XML::TreePP is needed, the instance provided is used instead of loading another copy.
Additionally, if this module has loaded an instance of XML::TreePP, this instance can be directly accessed or retrieved through this method.
If you want to only get the internally loaded instance of XML::TreePP, but want to not load a new instance and instead have undef returned if an instance is not already loaded, then use the get()
method.
my $tppobj = $tppx->get( 'tpp' );
warn "XML::TreePP is not loaded in XML::TreePP::XMLPath.\n" if !defined $tppobj;
This method was added in version 0.52
XML::TreePP
An instance of XML::TreePP that this object should use instead of, when needed, loading its own copy. If not provided, the currently loaded instance is returned. If an instance is not loaded, an instance is loaded and then returned.
returns
Returns the result of setting an instance of XML::TreePP in this object. Or returns the internally loaded instance of XML::TreePP. Or loads a new instance of XML::TreePP and returns it.
$tppx->tpp( new XML::TreePP ); # Sets the XML::TreePP instance to be used by this object
$tppx->tpp(); # Retrieve the currently loaded XML::TreePP instance
set
Set the value for a property in this object instance. This method can only be accessed in object oriented style.
This method was added in version 0.52
propertyname
The property to set the value for.
propertyvalue
The value of the property to set. If no value is given, the property is deleted.
returns
Returns the result of setting the value of the property, or the result of deleting the property.
$tppx->set( 'attr_prefix' ); # deletes the property attr_prefix
$tppx->set( 'attr_prefix' => '@' ); # sets the value of attr_prefix
get
Retrieve the value set for a property in this object instance. This method can only be accessed in object oriented style.
This method was added in version 0.52
propertyname
The property to get the value for
returns
Returns the value of the property requested
$tppx->get( 'attr_prefix' );
new
Create a new object instances of this module.
returns
An object instance of this module.
$tppx = new XML::TreePP::XMLPath();
charlexsplit
An analysis method for single character boundry and start/stop tokens
string
The string to analyse
boundry_start
The single character starting boundry separating wanted elements
boundry_stop
The single character stopping boundry separating wanted elements
tokens
A { start_char => stop_char } hash reference of start/stop tokens. The characters in
string
contained within a start_char and stop_char are not evaluated to match boundires.boundry_begin
Provide "1" if the beginning of the string should be treated as a
boundry_start
character.boundry_end
Provide "1" if the ending of the string should be treated as a
boundry_stop
character.returns
An arrary reference of elements
$elements = charlexsplit (
string => $string,
boundry_start => $charA, boundry_stop => $charB,
tokens => \@tokens,
boundry_begin => $char1, boundry_end => $char2 );
parseXMLPath
Parse a string that represents the path to a XML element or attribute in a XML document. The XML Path is something like XPath, and attempts to conform to the XPath standard, but it is far from being fully XPath compliant. XML::TreePP::XMLPath intends to be a method for accessing XML::TreePP parsed nodes.
Note that the XML attributes, known as "@attr" are transformed into "-attr". The preceeding (-) minus in place of the (@) at is the recognized format of attributes in the XML::TreePP module.
Being that this is intended to be a submodule of XML::TreePP, the format of '@attr' is converted to '-attr' to conform with how XML::TreePP handles attributes.
See: XML::TreePP->set( attr_prefix => '@' ); for more information. This module supports the default format, '-attr', of attributes. But as of version 0.52 this can be changed by setting this modules 'attr_prefix' property using the set()
method in object oriented programming. Example:
my $tppx = new XML::TreePP::XMLPath();
$tppx->set( attr_prefix => '@' );
XMLPath Filter by index and existance Also, as of version 0.52, there are two additional types of XMLPaths understood.
XMLPath with indexes, which is similar to the way XPath does it
$path = '/books/book[5]';
This defines the fith book in a list of book elements under the books root. When using this to get the value, the 5th book is returned. When using this to test an element, there must be 5 or more books to return true.
XMLPath by existance, which is similar to the way XPath does it
$path = '/books/book[author]';
This XMLPath represents all book elements under the books root which have 1 or more author child element. It does not evaluate if the element or attribute to evaluate has a value. So it is a test for existance of the element or attribute.
XMLPath
The XML path to be parsed.
returns
An arrary reference of array referenced elements of the XMLPath.
$parsedXMLPath = parseXMLPath( $XMLPath );
filterXMLDoc
To filter down to a subtree or set of subtrees of an XML document based on a given XMLPath
This method can also be used to determine if a node within an XML tree is valid based on the given filters in an XML path.
This method replaces the two methods getSubtree()
and validateAttrValue()
.
This method was added in version 0.52
XMLDocument
The XML document tree, or subtree node to validate. This is an XML document either given as plain text string, or as parsed by the
XML::TreePP-
parse()> method.The XMLDocument, when parsed, can be an ARRAY of multiple elements to evaluate, which would be validated as follows:
# when path is: context[@attribute] # returning: $subtree[item] if valid (returns all validated [item]) $subtree[item]->{'-attribute'} exists # when path is: context[@attribute="value"] # returning: $subtree[item] if valid (returns all validated [item]) $subtree[item]->{'-attribute'} eq "value" $subtree[item]->{'-attribute'}->{'value'} exists # when path is: context[5] # returning: $subtree[5] if exists (returns the fifth item if validated) $subtree['itemnumber'] # when path is: context[5][element="value"] # returning: $subtree[5] if exists (returns the fifth item if validated) $subtree['itemnumber']->{'element'} eq "value" $subtree['itemnumber']->{'element'}->{'value'} exists
Or the XMLDocument can be a HASH which would be a single element to evaluate. The XMLSubTree would be validated as follows:
# when path is: context[element] # returning: $subtree if validated $subtree{'element'} exists # when path is: context[@attribute] # returning: $subtree if validated $subtree{'-attribute'} eq "value" $subtree{'-attribute'}->{'value'} exists
XMLPath
The path within the XML Tree to retrieve. See
parseXMLPath()
returns
The parsed XML Document subtrees that are validated, or undef if not validated
You can retrieve the result set in one of two formats.
# Option 1 - An ARRAY reference to a list my $result = filterXMLDoc( $xmldoc, '/books' ); # $result is: # [ { book => { title => "PERL", subject => "programming" } }, # { book => { title => "All About Backpacks", subject => "hiking" } } ] # Option 2 - A list, or normal array my @result = filterXMLDoc( $xmldoc, '/books/book[subject="camping"]' ); # $result is: # ( { title => "campfires", subject => "camping" }, # { title => "tents", subject => "camping" } )
my $result = filterXMLDoc( $XMLDocument , $XMLPath );
my @result = filterXMLDoc( $XMLDocument , $XMLPath );
validateAttrValue
As of version 0.52, this method is deprecated. The method filterXMLDoc()
should be used instead. See this method's implementation illustration for the alternate example using filterXMLDoc()
.
Validate a subtree of a parsed XML document to have a parameter set in which an attribute matches a value.
XMLSubTree
The XML tree, or subtree, (element) to validate. This is an XML document parsed by the XML::TreePP->parse() method.
The XMLSubTree can be an ARRAY of multiple elements to evaluate. The XMLSubTree would be validated as follows:
$subtree[item]->{'attribute'} eq "value" $subtree[item]->{'attribute'}->{'value'} exists returning: $subtree[item] if valid (returns the first valid [item])
Or the XMLSubTree can be a HASH which would be a single element to evaluate. The XMLSubTree would be validated as follows:
$subtree{'attribute'} eq "value" $subtree{'attribute'}->{'value'} exists returning: $subtree if valid
params
Validate the element having an attribute matching value in this current XMLSubTree position
This is an array reference of
[["attr1","val"],["attr2","val"]]
, as in:my $params = [[ "MyKeyName" , "Value_to_match_for_KeyName" ]];
As of XMLPath version 0.52, one can define an element or attribute existance test the
getSubTree()
method because of its support in theparseXMLPath()
method. But this feature was already available in this method. The result of parsing this withparseXMLPath()
for use by this method is as follows:my $params = [[ "-id", undef ]]; # Test for existance of the attribute "id"
returns
The subtree that is validated, or undef if not validated
my @params = ( [ "element", "value" ], [ "-attribute", "value" ] );
$validatedXMLTree = validateAttrValue( $XMLTree , \@params );
# Alternately, you can do the same using the filterXMLDoc() method using
# the single period (.) which identifies the immediate root of the
# XML Document (or a XML Document node you provide instead).
# If $XMLTree can be either plain text or a XML::TreePP parsed XML Document
my $result = filterXMLDoc( $XMLTree, '[.[element="value"][@attribute="value"]]' );
my $result = filterXMLDoc( $XMLTree, [ ".", \@params ] );
getSubtree
As of version 0.52, this method is deprecated. The function filterXMLDoc()
should be used instead. See this method's implementation illustration for the alternate example using filterXMLDoc()
.
Starting in version 0.52, this method still returns the same single value as it did in version 0.51, but with additional filtering capabilities provided to it by filterXMLDoc()
. Also starting in version 0.52 this method can additionally return an array of values resulting from the match. See returns below.
Return a subtree of an XML tree from a given XMLPath. See parseXMLPath()
for the format of a XMLPath. This function returns the first subtree or an array of subtrees in the given XML tree found to match the given XMLPath.
If you want to retrieve all subtrees in the given XML tree which match the given XML path, you should ideally use the filterXMLDoc()
function.
This method actually executes filterXMLDoc()
and returns the first result set, or more precisely the first matching node and its subtree in the XML Doc. If the context of the caller is requesting a list or array, then all matching nodes and their subtrees will be returned to the caller as a list (array).
XMLTree
An XML::TreePP parsed XML document.
XMLPath
The path within the XML Tree to retrieve. See parseXMLPath()
returns
A subtree of a XML::TreePP parsed XMLTree found at the XMLPath and the caller is not requesting an array, otherwise a list of subtrees are returned. Depending on the XMLPath given, the returning value(s) could actually be string values and not referenced subtree nodes.
$XMLSubTree = getSubtree ( $XMLTree , $XMLPath );
@XMLSubTrees = getSubtree ( $XMLTree , $XMLPath );
# Alternately, you can do the same using the filterXMLDoc() method.
my $result = filterXMLDoc( $XMLTree, $XMLPath );
my @result = filterXMLDoc( $XMLTree, $XMLPath );
getAttributes
XMLTree
An XML::TreePP parsed XML document.
XMLPath
The path within the XML Tree to retrieve. See parseXMLPath()
returns
An array refrence of [{attribute=>value}], or undef if none found
In the case where the XML Path points at a multi-same-name element, the return value is a ref arrary of ref hashes, one hash ref for each element.
Example Returned Data:
XML Path points at a single named element [ {attr1=>val,attr2=>val} ] XML Path points at a multi-same-name element [ {attr1A=>val,attr1B=>val}, {attr2A=>val,attr2B=>val} ]
$attributes = getAttributes ( $XMLTree , $XMLPath );
getElements
Gets the child elements found at a specified XMLPath
XMLTree
An XML::TreePP parsed XML document.
XMLPath
The path within the XML Tree to retrieve. See parseXMLPath()
returns
An array refrence of [{element=>value}], or undef if none found
An array reference of a hash reference of elements (not attributes) and each elements XMLSubTree, or undef if none found. If the XMLPath points at a multi-valued element, then the subelements of each element at the XMLPath are returned as separate hash references in the returning array reference.
The format of the returning data is the same as the getAttributes() method.
The XMLSubTree is fetched based on the provided XMLPath. Then all elements found under that XMLPath are placed into a referenced hash table to be returned. If an element found has additional XML data under it, it is all returned just as it was provided.
Simply, this strips all XML attributes found at the XMLPath, returning the remaining elements found at that path.
If the XMLPath has no elements under it, then undef is returned instead.
$elements = getElements ( $XMLTree , $XMLPath );
EXAMPLES
Method: new
It is not necessary to create an object of this module. However, if you choose to do so any way, here is how you do it.
my $obj = new XML::TreePP::XMLPath;
This module supports being called by two methods.
- 1. By importing the functions you wish to use, as in:
-
use XML::TreePP::XMLPath qw( function1 function2 ); function1( args )
See IMPORTABLE METHODS section for methods available for import
- 2. Or by calling the functions in an object oriented mannor, as in:
-
my $tppx = new XML::TreePP::XMLPath; $tppx->function1( args )
Using either method works the same and returns the same output.
Method: charlexsplit
Here are three steps that can be used to parse values out of a string:
Step 1:
First, parse the entire string deliminated by the / character.
my $el = charlexsplit (
string => q{abcdefg/xyz/path[@key='val'][@key2='val2']/last},
boundry_start => '/',
boundry_stop => '/',
tokens => [qw( [ ] ' ' " " )],
boundry_begin => 1,
boundry_end => 1
);
dump( $el );
Output:
["abcdefg", "xyz", "path[\@key='val'][\@key2='val2']", "last"],
Step 2:
Second, parse the elements from step 1 that have key/val pairs, such that each single key/val is contained by the [ and ] characters
my $el = charlexsplit (
string => q( path[@key='val'][@key2='val2'] ),
boundry_start => '[',
boundry_stop => ']',
tokens => [qw( ' ' " " )],
boundry_begin => 0,
boundry_end => 0
);
dump( $el );
Output:
["\@key='val'", "\@key2='val2'"]
Step 3:
Third, parse the elements from step 2 that is a single key/val, the single key/val is delimintated by the = character
my $el = charlexsplit (
string => q{ @key='val' },
boundry_start => '=',
boundry_stop => '=',
tokens => [qw( ' ' " " )],
boundry_begin => 1,
boundry_end => 1
);
dump( $el );
Output:
["\@key", "'val'"]
Note that in each example the tokens
represent a group of escaped characters which, when analysed, will be collected as part of an element, but will not be allowed to match any starting or stopping boundry.
So if you have a start token without a stop token, you will get undesired results. This example demonstrate this data error.
my $el = charlexsplit (
string => q{ path[@key='val'][@key2=val2'] },
boundry_start => '[',
boundry_stop => ']',
tokens => [qw( ' ' " " )],
boundry_begin => 0,
boundry_end => 0
);
dump( $el );
Undesired output:
["\@key='val'"]
In this example of bad data being parsed, the boundry_stop
character ]
was never matched for the key2=val2
element.
And there is no error message. The charlexsplit method throws away the second element silently due to the token start and stop mismatch.
Method: parseXMLPath
use XML::TreePP::XMLPath qw(parseXMLPath);
use Data::Dump qw(dump);
my $parsedPath = parseXMLPath(
q{abcdefg/xyz/path[@key1='val1'][key2='val2']/last}
);
dump ( $parsedPath );
Output:
[
["abcdefg", undef],
["xyz", undef],
["path", [["-key1", "val1"], ["key2", "val2"]]],
["last", undef],
]
Method: filterXMLDoc
Filtering an XML Document, using an XMLPath, to find a node within the document.
#!/usr/bin/perl
use XML::TreePP;
use XML::TreePP::XMLPath qw(filterXMLDoc);
use Data::Dump qw(dump);
#
# The XML document data
my $xmldata=<<XMLEND;
<level1>
<level2>
<level3 attr1="val1" attr2="val2">
<attr3>val3</attr3>
<attr4/>
<attrX>one</attrX>
<attrX>two</attrX>
<attrX>three</attrX>
</level3>
<level3 attr1="valOne"/>
</level2>
</level1>
XMLEND
#
# Parse the XML docuemnt.
my $tpp = new XML::TreePP;
my $xmldoc = $tpp->parse($xmldata);
print "Output Test #1\n";
dump( $xmldoc );
#
# Retrieve the sub tree of the XML document at path "level1/level2"
my $xmlSubTree = filterXMLDoc($xmldoc, 'level1/level2');
print "Output Test #2\n";
dump( $xmlSubTree );
#
# Retrieve the sub tree of the XML document at path "level1/level2/level3[@attr1='val1']"
my $xmlSubTree = filterXMLDoc($xmldoc, 'level1/level2/level3[@attr1="val1"]');
print "Output Test #3\n";
dump( $xmlSubTree );
Output:
Output Test #1
{
level1 => {
level2 => {
level3 => [
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
},
{ "-attr1" => "valOne" },
],
},
},
}
Output Test #2
{
level3 => [
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
},
{ "-attr1" => "valOne" },
],
}
Output Test #3
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
}
Validating attribute and value pairs of a given node.
#!/usr/bin/perl
use XML::TreePP;
use XML::TreePP::XMLPath qw(filterXMLDoc);
use Data::Dump qw(dump);
#
# The XML document data
my $xmldata=<<XMLEND;
<paragraph>
<sentence language="english">
<words>Do red cats eat yellow food</words>
<punctuation>?</punctuation>
</sentence>
<sentence language="english">
<words>Brown cows eat green grass</words>
<punctuation>.</punctuation>
</sentence>
</paragraph>
XMLEND
#
# Parse the XML docuemnt.
my $tpp = new XML::TreePP;
my $xmldoc = $tpp->parse($xmldata);
print "Output Test #1\n";
dump( $xmldoc );
#
# Retrieve the sub tree of the XML document at path "paragraph/sentence"
my $xmlSubTree = filterXMLDoc($xmldoc, "paragraph/sentence");
print "Output Test #2\n";
dump( $xmlSubTree );
#
my (@params, $validatedSubTree);
#
# Test the XML Sub Tree to have an attribute "-language" with value "german"
@params = (['-language', 'german']);
$validatedSubTree = filterXMLDoc($xmlSubTree, [ ".", \@params ]);
print "Output Test #3\n";
dump( $validatedSubTree );
#
# Test the XML Sub Tree to have an attribute "-language" with value "english"
@params = (['-language', 'english']);
$validatedSubTree = filterXMLDoc($xmlSubTree, [ ".", \@params ]);
print "Output Test #4\n";
dump( $validatedSubTree );
Output:
Output Test #1
{
paragraph => {
sentence => [
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
},
{
"-language" => "english",
punctuation => ".",
words => "Brown cows eat green grass",
},
],
},
}
Output Test #2
[
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
},
{
"-language" => "english",
punctuation => ".",
words => "Brown cows eat green grass",
},
]
Output Test #3
undef
Output Test #4
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
}
Method: validateAttrValue
#!/usr/bin/perl
use XML::TreePP;
use XML::TreePP::XMLPath qw(getSubtree validateAttrValue);
use Data::Dump qw(dump);
#
# The XML document data
my $xmldata=<<XMLEND;
<paragraph>
<sentence language="english">
<words>Do red cats eat yellow food</words>
<punctuation>?</punctuation>
</sentence>
<sentence language="english">
<words>Brown cows eat green grass</words>
<punctuation>.</punctuation>
</sentence>
</paragraph>
XMLEND
#
# Parse the XML docuemnt.
my $tpp = new XML::TreePP;
my $xmldoc = $tpp->parse($xmldata);
print "Output Test #1\n";
dump( $xmldoc );
#
# Retrieve the sub tree of the XML document at path "paragraph/sentence"
my $xmlSubTree = getSubtree($xmldoc, "paragraph/sentence");
print "Output Test #2\n";
dump( $xmlSubTree );
#
my (@params, $validatedSubTree);
#
# Test the XML Sub Tree to have an attribute "-language" with value "german"
@params = (['-language', 'german']);
$validatedSubTree = validateAttrValue($xmlSubTree, \@params);
print "Output Test #3\n";
dump( $validatedSubTree );
#
# Test the XML Sub Tree to have an attribute "-language" with value "english"
@params = (['-language', 'english']);
$validatedSubTree = validateAttrValue($xmlSubTree, \@params);
print "Output Test #4\n";
dump( $validatedSubTree );
Output:
Output Test #1
{
paragraph => {
sentence => [
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
},
{
"-language" => "english",
punctuation => ".",
words => "Brown cows eat green grass",
},
],
},
}
Output Test #2
[
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
},
{
"-language" => "english",
punctuation => ".",
words => "Brown cows eat green grass",
},
]
Output Test #3
undef
Output Test #4
{
"-language" => "english",
punctuation => "?",
words => "Do red cats eat yellow food",
}
Method: getSubtree
#!/usr/bin/perl
use XML::TreePP;
use XML::TreePP::XMLPath qw(getSubtree);
use Data::Dump qw(dump);
#
# The XML document data
my $xmldata=<<XMLEND;
<level1>
<level2>
<level3 attr1="val1" attr2="val2">
<attr3>val3</attr3>
<attr4/>
<attrX>one</attrX>
<attrX>two</attrX>
<attrX>three</attrX>
</level3>
<level3 attr1="valOne"/>
</level2>
</level1>
XMLEND
#
# Parse the XML docuemnt.
my $tpp = new XML::TreePP;
my $xmldoc = $tpp->parse($xmldata);
print "Output Test #1\n";
dump( $xmldoc );
#
# Retrieve the sub tree of the XML document at path "level1/level2"
my $xmlSubTree = getSubtree($xmldoc, 'level1/level2');
print "Output Test #2\n";
dump( $xmlSubTree );
#
# Retrieve the sub tree of the XML document at path "level1/level2/level3[@attr1='val1']"
my $xmlSubTree = getSubtree($xmldoc, 'level1/level2/level3[@attr1="val1"]');
print "Output Test #3\n";
dump( $xmlSubTree );
Output:
Output Test #1
{
level1 => {
level2 => {
level3 => [
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
},
{ "-attr1" => "valOne" },
],
},
},
}
Output Test #2
{
level3 => [
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
},
{ "-attr1" => "valOne" },
],
}
Output Test #3
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
}
See validateAttrValue() EXAMPLES section for more usage examples.
Method: getAttributes
#!/usr/bin/perl
#
use XML::TreePP;
use XML::TreePP::XMLPath qw(getAttributes);
use Data::Dump qw(dump);
#
# The XML document data
my $xmldata=<<XMLEND;
<level1>
<level2>
<level3 attr1="val1" attr2="val2">
<attr3>val3</attr3>
<attr4/>
<attrX>one</attrX>
<attrX>two</attrX>
<attrX>three</attrX>
</level3>
<level3 attr1="valOne"/>
</level2>
</level1>
XMLEND
#
# Parse the XML docuemnt.
my $tpp = new XML::TreePP;
my $xmldoc = $tpp->parse($xmldata);
print "Output Test #1\n";
dump( $xmldoc );
#
# Retrieve the sub tree of the XML document at path "level1/level2/level3"
my $attributes = getAttributes($xmldoc, 'level1/level2/level3');
print "Output Test #2\n";
dump( $attributes );
#
# Retrieve the sub tree of the XML document at path "level1/level2/level3[attr3=""]"
my $attributes = getAttributes($xmldoc, 'level1/level2/level3[attr3="val3"]');
print "Output Test #3\n";
dump( $attributes );
Output:
Output Test #1
{
level1 => {
level2 => {
level3 => [
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
},
{ "-attr1" => "valOne" },
],
},
},
}
Output Test #2
[{ attr1 => "val1", attr2 => "val2" }, { attr1 => "valOne" }]
Output Test #3
[{ attr1 => "val1", attr2 => "val2" }]
Method: getElements
#!/usr/bin/perl
#
use XML::TreePP;
use XML::TreePP::XMLPath qw(getElements);
use Data::Dump qw(dump);
#
# The XML document data
my $xmldata=<<XMLEND;
<level1>
<level2>
<level3 attr1="val1" attr2="val2">
<attr3>val3</attr3>
<attr4/>
<attrX>one</attrX>
<attrX>two</attrX>
<attrX>three</attrX>
</level3>
<level3 attr1="valOne"/>
</level2>
</level1>
XMLEND
#
# Parse the XML docuemnt.
my $tpp = new XML::TreePP;
my $xmldoc = $tpp->parse($xmldata);
print "Output Test #1\n";
dump( $xmldoc );
#
# Retrieve the multiple same-name elements of the XML document at path "level1/level2/level3"
my $elements = getElements($xmldoc, 'level1/level2/level3');
print "Output Test #2\n";
dump( $elements );
#
# Retrieve the elements of the XML document at path "level1/level2/level3[attr3="val3"]
my $elements = getElements($xmldoc, 'level1/level2/level3[attr3="val3"]');
print "Output Test #3\n";
dump( $elements );
Output:
Output Test #1
{
level1 => {
level2 => {
level3 => [
{
"-attr1" => "val1",
"-attr2" => "val2",
attr3 => "val3",
attr4 => undef,
attrX => ["one", "two", "three"],
},
{ "-attr1" => "valOne" },
],
},
},
}
Output Test #2
[
{ attr3 => "val3", attr4 => undef, attrX => ["one", "two", "three"] },
undef,
]
Output Test #3
[
{ attr3 => "val3", attr4 => undef, attrX => ["one", "two", "three"] },
]
AUTHOR
Russell E Glaue, http://russ.glaue.org
SEE ALSO
XML::TreePP
COPYRIGHT AND LICENSE
Copyright (c) 2008 Center for the Application of Information Technologies. All rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.