This is and xml parser and generator and manipulator.This one uses DOM XML Functions
Supports:
1. XML Attributes
2. Namespaces
3. Namespaced attributes
4. CDATA sections
Here I list some of the topics in this document that may be of greater interest.
2. XML Parsing
5. PHP Code Generation for accessing a node
XML corresponding a crXml object is obtained by callng xml() method.
Please take a look at the examples.
Example 1:
Code |
Output |
$x = new crXml();
$x->person = "sandeep"; echo $x->xml(); |
<?xml
version="1.0" encoding="UTF-8"?> |
Example 2:
Code |
Output |
$x=new crXml(); $x->records->name='sandeep'; echo $x->xml(); |
<?xml
version="1.0" encoding="UTF-8"?> |
Example 3:
Code |
Output |
$x=new crXml(); $x->records[5]->name='sandeep'; echo $x->xml(); |
<?xml
version="1.0" encoding="UTF-8"?> |
In the above example a value is assigned to the fifth `records` child of the root node.
As there are no presceding 4 nodes, they are created by the class itself.
Example 4: Adding attributes
Code |
Output |
$x = new crXml(); $x->record->name = 'sandeep'; $x->record->name['sex'] = 'Male'; $x->record->name['age'] = '29'; echo $x->xml(); |
<?xml
version="1.0" encoding="UTF-8"?> |
A namespace declaration can be added to a node using the addNameSpace method.
This method accepts an array.
Thus multiple namespace declarations can be added to the
node at once.
Code |
Output |
$crxml = new crXml(); $crxml->records-> addNameSpace(array('prfx'=>'http://google.com')); $crxml->records->{'prfx:person'}->name = 'sandeep'; echo $crxml->xml(); |
<?xml version="1.0"
encoding="UTF-8"?> |
Namespaced nodes can be
added without using addNameSpace function also. See
below examples.
An alternative syntax to generate a Namespaced node is to
add the declaration of the namespace
in same node itself .
Here is how. This one does not use any function
Code |
Output |
$crxml = new crXml(); $crxml->records->{'http://google.com|person|prfx'}->name = 'sandeep'; echo $crxml->xml(); |
<?xml
version="1.0" encoding="UTF-8"?> |
In the above code the ‘|’ character is used to separate namespaceURI, nodeName and the prefix that
should be associated with that name space. The prefix part is optional. If omitted the node will
become the start of a default
namespace
Example 6: Namespaced Attributes
Code |
Output |
$crxml = new crXml(); $crxml->record-> addNameSpace(array('prfx'=>'http://google.com')); $crxml->record->name = 'sandeep'; $crxml->record->name['prfx:sex'] = 'Male'; $crxml->record->name['age'] = '29'; echo $crxml->xml(); |
<?xml
version="1.0" encoding="UTF-8"?> sandeep </name> |
Please note that all the values can be retrived using the same notation used to assign it.
In the above example,
echo
$crxml->record->name['prfx:sex'];
would print “Male”.
echo $crxml->record->name; would print “sandeep”.
Example 7:
This example illustrates how to add many nodes with same name to a parent node.
<?php
$xml = new crXml();
$year = $xml->year;
foreach(range(1,12) as $m)
{
$year->month[$m-1]->noOfDays = date('t',mktime(0,0,0,$m,$m,2000));
$year->month[$m-1]->shortName = date('M',mktime(0,0,0,$m,$m,2000));
$year->month[$m-1]['name']=date('F',mktime(0,0,0,$m,$m,2000));
}
echo $xml->xml();
?>
Output:
<?xml
version="1.0" encoding="UTF-8"?>
<year>
<month name="January">
<noOfDays>31</noOfDays>
<shortName>Jan</shortName>
</month>
<month name="February">
<noOfDays>29</noOfDays>
<shortName>Feb</shortName>
</month>
<month name="March">
<noOfDays>31</noOfDays>
<shortName>Mar</shortName>
</month>
<month name="April">
<noOfDays>30</noOfDays>
<shortName>Apr</shortName>
</month>
<month name="May">
<noOfDays>31</noOfDays>
<shortName>May</shortName>
</month>
<month name="June">
<noOfDays>30</noOfDays>
<shortName>Jun</shortName>
</month>
<month name="July">
<noOfDays>31</noOfDays>
<shortName>Jul</shortName>
</month>
<month name="August">
<noOfDays>31</noOfDays>
<shortName>Aug</shortName>
</month>
<month name="September">
<noOfDays>30</noOfDays>
<shortName>Sep</shortName>
</month>
<month name="October">
<noOfDays>31</noOfDays>
<shortName>Oct</shortName>
</month>
<month name="November">
<noOfDays>30</noOfDays>
<shortName>Nov</shortName>
</month>
<month name="December">
<noOfDays>31</noOfDays>
<shortName>Dec</shortName>
</month>
</year>
Now an echo $xml->year->month[2]['name']; would print ‘March’.Because nodes are indexed from 0.
Example 8:Adding a CDATA Section:
To add a cdata section, cast the string into an object while assigning it to nodes.
Code |
Output |
$xmlOne=new crXml(); |
<?xml version="1.0"
encoding="UTF-8"?> |
Code |
Output |
$xmlOne=new crXml(); |
<?xml version="1.0"
encoding="UTF-8"?> sandeep </person> |
Code |
Output |
<?php |
<?xml version="1.0"
encoding="UTF-8"?> Sandeep </prfx:person> |
An XML String is loaded into the class using function loadXML();
$x=new crXml();
$xml=<<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<records>
<name>sandeep</name>
</records>
EOB;
$crxml->loadXML($xml);
After this, Nodes can be accessed by a combination of object and array notation. to get the n-th child node of a node 'parentnode'
with name 'childnode' use notation
$crXmlObj->.....->parentnode->childnode[n]
Please go through the following examples and please note the comments.
Example 1. Simple
Example
<?php
include 'crXml.php';
$crxml=new crXml();
$xml=<<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<records>
<name>sandeep</name>
</records>
EOB;
$crxml->loadXML($xml);
echo $crxml->records->name; //echos 'sandeep'
?>
Example 2. Accessing
n-th child of a node
<?php
include 'crXml.php';
$crxml=new crXml();
$xml=<<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<records>
<name>sandeep</name>
<name>max</name>
</records>
EOB;
$crxml->loadXML($xml);
echo $crxml->records->name[1]; //echos 'max'
?>
Example 3: Dealing with NameSpaces
Type 1:
<?php
$crxml=new crXml();
$xml=<<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<records xmlns:prf = 'http://yahoo.com'>
<prf:name>sandeep</prf:name>
<prf:name>max</prf:name>
</records>
EOB;
$crxml->loadXML($xml);
echo $crxml->records->{'prf:name'}[1]; //echos 'max'
Type 2: Accessing namespace without prefix(Default
Namespaces).
<?php
$crxml=new crXml();
$xml=<<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<records xmlns = 'http://yahoo.com'>
<name>sandeep</name>
<name>max</name>
</records>
EOB;
$crxml->loadXML($xml);
$crxml->{'http://yahoo.com|records'}->name; // uses '|' charecter to separate namespace URI and nodename;echos 'sandeep'
$crxml->{'http://yahoo.com|records'}->name[1]; // echos 'max'
Type 3. accessing nodes with namespaces defenition
in the same node
<?php
$crxml=new crXml();
$xml=<<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<prf:records xmlns:prf = 'http://yahoo.com'>
<prf:name>sandeep</prf:name>
<prf:name>max</prf:name>
</prf:records>
EOB;
$crxml->loadXML($xml);
echo $crxml->{'prf:records'}->{'prf:name'}[1]; // echos 'max'
This is a very useful function that can actually generate the php code to access
a certain node.
For example
consider the following SOAP Response XML
<?xml
version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<GeteBayOfficialTimeResponse xmlns="urn:ebay:apis:eBLBaseComponents">
<Timestamp>2005-10-28T01:01:04.668Z</Timestamp>
<Ack>Success</Ack>
<Version>429</Version>
<Build>e429_intl_Bundled_1949355_R1</Build>
</GeteBayOfficialTimeResponse>
</soapenv:Body>
</soapenv:Envelope>
You load this xml into a crXml '$srcXML'
object using loadXML($xmlStr)
method. Now say, you need to access the timestamp node.
you only have to call the search() function on the $srcXML object. This is shown below.
print_r($srcXML->search('Timestamp'));
This prints the dump of the array returned by the search function.
Please note the 'accessStatement' element .
This element shows how the 'Timestamp' node
should be accessed.
Array
(
[0] => Array
(
[nodeName] => Timestamp
[namespaceURI] => urn:ebay:apis:eBLBaseComponents
[nodeValue] => 2005-10-28T01:01:04.668Z
[accessStatement] => ...->{'soapenv:Envelope'}->{'soapenv:Body'}->{'urn:ebay:apis:eBLBaseComponents|GeteBayOfficialTimeResponse'}->{'urn:ebay:apis:eBLBaseComponents|Timestamp'}
)
)
Here accessElement contains
...->{'soapenv:Envelope'}->{'soapenv:Body'}->{'urn:ebay:apis:eBLBaseComponents|GeteBayOfficialTimeResponse'}->{'urn:ebay:apis:eBLBaseComponents|Timestamp'}
so an echo
$srcXML->{'soapenv:Envelope'}->{'soapenv:Body'}->{'urn:ebay:apis:eBLBaseComponents|GeteBayOfficialTimeResponse'}->{'urn:ebay:apis:eBLBaseComponents|Timestamp'}
Will echo its value here it is
'2005-10-28T01:01:04.668Z'
You can search namespaced nodes too using the search
function. just use the nodename
with prefix as it appears in XML.
for Eg:
$srcXML->search('soapenv:Body');
Example 4: Iterating over a nodes
children.
The crXml object is iterable, so a simple foreach can be used to iterate over a node’s children. Please look at the below example.
<?php
include
'crXml.php';
$xml = <<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<year>
<month name="January">
<noOfDays>31</noOfDays>
<shortName>Jan</shortName>
</month>
<month name="February">
<noOfDays>29</noOfDays>
<shortName>Feb</shortName>
</month>
<month name="March">
<noOfDays>31</noOfDays>
<shortName>Mar</shortName>
</month>
</year>
EOB;
$x = new crXml();
$x->loadXML($xml);
foreach
($x->year as $k => $v) {
echo $k, ',' , $v['name'], ',' , $v->shortName,"<br/>";
}
In the above foreach, the nodes name is returned in the $k, and the nodes value is returned in the $v.
Note that each $v
is a crXml
object. So its children and attributes can be accessed in manner described
in previous examples.
So the above code outputs
month,January,Jan
month,February,Feb
month,March,Mar
<?php
include
'crXml.php'
;
$x
= new
crXml
();
$xmlStr
= <<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<records>
<person age="15">
<name>
alex
</name>
</person>
<person age="28">
<name>
sandeep
</name>
</person>
</records>
EOB;
$x
->
loadXML
(
$xmlStr
);
$x
->
records
->
person
[
1
][
'age'
] =
'30'
;
//sets second persons attribute to 30
$x
->
records
->
person
[
1
]->
name
=
'albert'
;
// sets child node ‘name’ of second person to ‘albert’
$x
->
records
->
person
[
2
] =
$x
->
records
->
person
[
1
];
// create a third `person` node and assign it the value of second 'person' node.
echo
$x
->
xml
();
?>
Outputs XML:
Source XML ($s)
|
Destination XML($d)
|
|
<?xml version="1.0"
encoding="utf-8"?>
|
<?xml version="1.0"
encoding="utf-8"?> |
|
$d->records->person[1] = $s->records->person[0];
|
<?xml version="1.0" encoding="UTF-8"?>
|
The destination nodes attribute and child
nodes are cleared. The attributes and children from Source node is copied to destination making
the two nodes equalent.If the source node is of
different namespace the namespace is not copied |
$d->records->person[1] = $s->records->personNew;
|
<?xml version="1.0" encoding="UTF-8"?>
|
Same as above, The attributes and childnodes of
destination node are deleted. The attributes and children from Source node are
copied to destination making the two nodes equivalent. If the source node is
of different namespace the namespace is not copied |
$s->records->person[0]->appendTo($d->records);
|
<?xml version="1.0"
encoding="UTF-8"?> |
The source node is
appended to the child nodes of the
destination |
$d->records->person[1]->name = $s->records->person[0]->name;
|
<?xml version="1.0" encoding="UTF-8"?> <records> <person age="15" sex="male"> <name>Max</name> </person> <person age="32" sex="female"> <name>John</name> </person> </records> |
|
$d->records->person[1]->appendNode(
crxml::factory("<newNode>nodeV<person/></newNode>")
);
|
<?xml version="1.0" encoding="UTF-8"?> <records> <person age="15" sex="male"> <name>Max</name> </person> <person age="32" sex="female"> <name>Liz</name> <newNode>newNodeValue</newNode> </person> </records> |
The factory method
used to generate a xml node, and append to the
second person node. |