Using SAX to Parse XML Documents


You can parse the XML document using the two methods , SAX and DOM. When you parse the XML document using DOM, it occupies greater memory space to represent data in a tree structure, which results in slow performance. SAX overcomes the drawbacks of the DOM parser, and provides fast and efficient use of memory by reading the document in chunks . The Expat parser implements the SAX parser.

Using SAX to Modify a Document

You can update XML documents by adding elements and attributes, removing elements, and changing the text of the XML document. For example, an XML document contains information pertaining to the students of a school. You need to add information about the students who have enrolled in a particular semester, and remove information about the students who have left the school.

To modify the information in the XML document, you need to create a filter by implementing the AbstractFilter class.

Listing 2-7 shows how to add information pertaining to a student in the XML document, using SAX:

Listing 2-7: Adding Data in XML Document Using SAX
start example
 <?php include_once("/class_sax_filters.php"); class FilterAddStudent extends AbstractFilter {    var $studentDetail=Array();    function AddStudent($id, $name, $age, $address, $standard)    {       $detail=Array();       $detail["id"]=$id;       $detail["name"]=$name;       $detail["age"]=$age;       $detail["address"]=$address;       $detail["standard"]=$standard;       $this->studentDetail[]=$detail;    }    function StartElementHandler($element_name, $attributes)    {       $this->listener->StartElementHandler($element_name, $attributes);       if($element_name=="STUDENTDETAIL")       {          foreach($this->studentDetail as $student)          {             $this->listener->StartElementHandler("STUDENT", Array("id"             =>$student["id"]));             //For student name             $this->listener->StartElementHandler("NAME", Array());             $this->listener->CharacterDataHandler($student["name"]);             $this->listener->EndElementHandler("NAME");             //For student age             $this->listener->StartElementHandler("AGE", Array());             $this->listener->CharacterDataHandler($student["age"]);             $this->listener->EndElementHandler("AGE");             //For student address             $this->listener->StartElementHandler("ADDRESS", Array());             $this->listener->CharacterDataHandler($student["address"]);             $this->listener->EndElementHandler("ADDRESS");             //For student standard             $this->listener->StartElementHandler("STANDARD", Array());             $this->listener->CharacterDataHandler($student["standard"]);             $this->listener->EndElementHandler("STANDARD");             $this->listener->EndElementHandler("STUDENT");          }       }    }    function EndElementHandler($element_name)    {       $this->listener->EndElementHandler($element_name);    }    function CharacterDataHandler($data)    {       $this->listener->CharacterDataHandler($data);    } } $f1 = new ExpatParser("student.xml"); $f1->ParserSetOption(XML_OPTION_CASE_FOLDING, 0); $f2 = new FilterAddStudent(); $f2->AddStudent("S003", "Jack", "14","New York","9"); $f2->AddStudent("S004", "Jim", "14","New York","9"); $f3 = new FilterOutput(); $f2->SetListener($f3); $f1->SetListener($f2); $f1->Parse(); ?> 
end example
 

In the above listing:

  • The FilterAddStudent filter is implemented using the AbstractFilter class.

  • The FilterAddStudent filter contains the AddStudent() function that adds records of the students to the XML document.

  • The AddStudent() function stores the student details in the StudentDetail array, which is accessed by the event handlers to add new student records in the existing XML document.

Listing 2-8 shows the original XML document:

Listing 2-8: Contents of the XML Document
start example
 <?xml version="1.0" ?>  <studentdata> <student> <name id="s001">George</name>  <age>15</age>  <address>New York</address>  <standard>10</standard>  </student> <student> <name id="s001">John</name>  <age>15</age>  <address>New York</address>  <standard>10</standard>  </student> </studentdata> 
end example
 

Figure 2-3 shows the output of Listing 2-7:

click to expand: this figure shows the information about the records of two students added to the xml document.
Figure 2-3: Adding Data

Using SAX, you can remove data from the XML document by creating a filter that is implemented by the AbstractFilter class, as shown in Listing 2-9:

Listing 2-9: Removing Data in XML Document Using SAX
start example
 <? include_once("/class_sax_filters.php"); class FilterRemoveStudent extends AbstractFilter {    var $studentDetail = Array();    var $flag = 0;    function RemoveStudent($id)    {       $this->studentDetail[] = $id;    }    function StartElementHandler($element_name, $attributes)    {       if($element_name == "STUDENT")       {         if(in_array($attributes["ID"],$this->studentDetail))          {             $this->flag = 1;          }       }       if(!$this->flag)       {          $this->listener->StartElementHandler($element_name, $attributes);       }    }    function EndElementHandler($element_name)    {       if (!$this->flag)       {          $this->listener->EndElementHandler($element_name);       }       else       {          if($element_name=="STUDENT")          {             $this->flag=0;          }       }    }    function CharacterDataHandler($data)    {       if(!$this->flag)       {          $this->listener->CharacterDataHandler($data);       }    } } $fep = new ExpatParser("student.xml"); $frs = new FilterRemoveStudent(); $frs->RemoveStudent("S001"); $fou = new FilterOutput(); $frs->SetListener($fou); $fep->SetListener($frs); $fep->Parse(); ?> 
end example
 

In the above listing:

  • The FilterRemoveStudent filter is implemented using the AbstractFilter class.

  • The FilterRemoveStudent filter contains the RemoveStudent() function that removes the specified student s records from the XML document.

  • The RemoveStudent() function accepts the student id attribute as an argument. The RemoveStudent() function stores student ID in the StudentDetail variable, which is accessed by the event handlers to remove a student record from the existing XML document.

Figure 2-4 shows the output of Listing 2-9:

click to expand: this figure shows the information about one student, because the detail of the other student is removed from the xml document.
Figure 2-4: Removing Data

Using SAX to Query a Document

Querying a document refers to the process of traversing the XML document and searching for specific information. For example, an XML document contains information pertaining to the students of a school. You can query the XML document to search for the students who live in New York City.

Using SAX, you can query an XML document by creating a filter that is implemented by AbstractFilter, as shown in Listing 2-10:

Listing 2-10: Querying an XML Document Using SAX
start example
 <?php include_once("/class_sax_filters.php"); class FilterQueryStudent extends AbstractFilter {    var $detail = Array();    var $stud = Array();    var $st;    function RetrieveDetails()    {       return $this->detail;    }    function StartElementHandler($element_name, $attributes)    {       $this->st='';       if ($element_name <> "STUDENTDETAIL" && $element_name <> "STUDENT")    {       $this->st=$element_name;       $this->stud[$this->st]='';    } } function EndElementHandler($element_name) {    if($element_name == "STUDENT")    {       if(((trim($this->stud["ADDRESS"]))=="New York") &&       (trim($this->stud["AGE"])>=15))       {          $this->detail[]=$this->stud;       }       $this->stud = Array();       }    }    function CharacterDataHandler($data)    {       if($this->st)       {          if(!empty($data))          {             $this->stud[$this->st] .= $data;          }       }    } } $tests=Array(); $f1 = new ExpatParser("student.xml"); $f2 = new FilterQueryStudent(); $f1->SetListener($f2); $f1->Parse(); $tests=$f1->listener->RetrieveDetails(); $num=count($tests); for($i=0;$i<$num;$i++) {    foreach($tests[$i] as $key => $value)    {       print "<b>$key=$value</b><br/>";    } } ?> 
end example
 

In the above listing:

  • The AbstractFilter class implements the FilterQueryStudent filter.

  • The FilterQueryStudent filter contains the RetrieveDetails() function, which retrieves the records of students that satisfy the specified condition.

  • The EndElementHandler() function checks if the address of the student is New York and the age of the student is greater than or equal to 15.

Figure 2-5 shows the output of Listing 2-10:

click to expand: this figure shows the records of the students who are 15 years or older in age, and live in new york.
Figure 2-5: Output of Querying a Document

Using SAX to Generate an XML Document

Using SAX, you can generate an XML document from various sources, such as database, text file, and objects. You need to create a parser by implementing the AbstractSAXFilter class for generating the XML document.

For example, you can use the content of the student.txt text file to write an XML document. The student.txt file is shown below:

 George, English John, French Jack, Physics Jim, French Jack, English Jim, Physics George, Physics John, Physics 

Convert the student.txt text file into an XML document, using SAX, as shown in Listing 2-11:

Listing 2-11: Generating XML Data from a Text File
start example
 <?php include_once("/class_sax_filters.php"); class StudentParser extends AbstractSAXParser {    var $studentDetail = Array();    function StudentParser($textfile)    {       $xml_parser=new ParseStudent();       $xml_parser->ParseTextFile($textfile);       $this->studentDetail=$xml_parser->GetStudents();    }    function Parse()    {       $this->StartElementHandler($this,"STUDENTDETAIL",Array());       foreach($this->studentDetail as $student => $subjects)       {          $this->StartElementHandler($this, "STUDENT",Array());          $this->StartElementHandler($this, "NAME",Array());          $this->CharacterDataHandler($this, XmlEntities($student));          $this->EndElementHandler($this,"NAME");          $this->StartElementHandler($this, "SUBJECTS",Array());          foreach ($subjects as $subject)          {             $this->StartElementHandler($this, "SUBJECT",Array());             $this->CharacterDataHandler($this, XmlEntities($subject));             $this->EndElementHandler($this,"SUBJECT");          }          $this->EndElementHandler($this, "SUBJECTS");          $this->EndElementHandler($this, "STUDENT");       }       $this->EndElementHandler($this,"STUDENTDETAIL");    } } // Class that writes the XML data manually. class ParseStudent {    var $studentDetail = Array();    function ParseTextFile($textfile)    {       $fp=fopen($textfile,"r");       if (!$fp)       {          return 0;       }       $text=fread($fp, filesize($textfile));       return $this->ParseText($text);    }    function GetStudents()    {       return $this->studentDetail;    }    function ParseText($text)    {       $entries = Array();       $entry = Array();       $entries = explode("\n",$text);       foreach( $entries as $entry)       {          $entry = chop($entry);          $entry = explode(",", $entry);          if (!isset($this->studentDetail[$entry[0]]))          {             $this->studentDetail[$entry[0]]=Array();          }          $this->studentDetail[$entry[0]][]=$entry[1];       }       return 1;    } } // Function that overwrites the special character with the XML entities. function XmlEntities($data) {    $pos=0;    $len=strlen($data);    $escdata ="";    for(;$pos<$len;)    {       $char=substr($data,$pos,1);       $num = Ord($char);       switch($num)       {          case 34:          $char= "";          break;          case 38:          $char = "&";          break;          case 39:          $char = "&apos;";          break;          case 60:          $char = "<";          break;          case 62:          $char = ">";          break;          default:          if ($num < 32)          $char = ("&#".strval($num).";");          break;      }       $escdata .= $char;       $pos++;    }    return $escdata; } $f1=new StudentParser("student.txt"); $f2=new FilterOutput(); $f1->SetListener($f2); $f1->Parse(); ?> 
end example
 

In the above listing:

  • The parser, StudentParser, parses the student.txt text file, using the ParseStudent parsing class.

  • The parsing class reads the text file and stores the content according to the number of lines in the text file.

  • The chop() function stores the content of text file in the entry array, and the explode() function splits the text file using a string delimiter .

  • The comma delimiter divides each line into two words, and stores these words in the studentDetail array.

Figure 2-6 shows the output of Listing 2-11:

click to expand: this figure shows the xml data that is generated from the text file.
Figure 2-6: Output of Listing 2-11
Note  

You can create a well- formed XML document by encoding the required functions.

Using SAX to Create PHP Objects from XML

Using SAX, you can create PHP objects from an XML document. The SAX parser creates objects corresponding to each element in the XML document. These objects are represented as PHP objects using the SAX filters, and their references are stored in an array. For example, if an XML document contains information pertaining to students; it can be represented as the student object.

Listing 2-12 shows the content of the XML file that contains information pertaining to students:

Listing 2-12: Content of the XML File
start example
 <?xml version="1.0"?> <studentdetail> <student> <name>George</name> <marks>75</marks> </student> <student> <name>John</name> <marks>85</marks> </student> </studentdetail> 
end example
 

The above listing shows the elements of the XML document that are converted to the PHP objects.

The parser parses the XML document, finds the <student> tag, creates the student object, and stores its reference in an array. When the parser finds the <name> and <marks> tags, it assigns the value to the name and marks property of the student objects respectively.

Listing 2-13 shows how to create PHP objects from the XML document:

Listing 2-13: Creating PHP Objects from XML Document
start example
 <?php include_once("/class_sax_filters.php"); class Student {    var $name;    var $marks;    function GetName()    {       return $this->name;    }    function GetMarks()    {       return $this->marks;    }    function SetName($name)    {       $this->name=$name;    }    function SetMarks($marks)    {       $this->marks=$marks;    } } class FilterNull extends AbstractFilter { } class FilterStudentObject extends AbstractFilter {    var $count=0;    var $student;    var $sub_element=0;    var $studentDetail=Array();    function GetStudents()    {       return $this->studentDetail;    }    function StartElementHandler($element_name, $attributes)    {       if($element_name=="STUDENT")       {       $this->studentDetail[]=new Student();       $this->count=1;       }       else       {          if($this->count)          {             $this->sub_element=$element_name;          }       }       $this->listener->StartElementHandler($element_name, $attributes);    }    function EndElementHandler($element_name)    {       $this->sub_element=0;       if($element_name == "STUDENT")       {          $this->count=0;       }       $this->listener->EndElementHandler($element_name);    }    function CharacterDataHandler($cdata)    {       if($this->count && $this->sub_element)       {        $getMethod="get".strtoupper(substr($this->sub_element,0,1)).substr        ($this->sub_element,1);($this->sub_element,0,1)).substr($this->sub_element,1);        $sub=$this->studentDetail[count($this->studentDetail)-1]->$getMethod();        $this->studentDetail[count($this->studentDetail)-1]->$setMethod($sub.$cdata);       }       $this->listener->CharacterDataHandler($cdata);    } } $f1=new ExpatParser("student.xml"); $f2=new FilterStudentObject(); $f3=new FilterNull(); $f2->SetListener($f3); $f1->SetListener($f2); $f1->Parse(); $studentDetail=$f1->listener->GetStudents(); print_r($studentDetail); $num=count($studentDetail); print "<br/>"; for($i=0;$i<$num;$i++) {    foreach($studentDetail[$i] as $key => $value)    {       print "<b>$key=$value</b></br/>";    } } ?> 
end example
 

In the above listing:

  • The parser creates the objects of the student element and stores them in the studentDetail array.

  • The Student class creates the functions for retrieving the XML data. The StudentCreateObject filter parses the XML document and creates the objects corresponding to each element.

  • The FilterNull class is an empty user -defined class that does not contain any function. This class specifies that the output of the StudentCreateObject filter is not displayed in the XML format.

Figure 2-7 shows the output of Listing 2-13:

click to expand: this figure shows that the objects are stored in the array, which displays the key value pairs of the objects.
Figure 2-7: Creating PHP Objects
Note  

The print_r() function displays how the array elements are stored in the array.




Integrating PHP and XML 2004
Integrating PHP and XML 2004
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 51

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net