summaryrefslogtreecommitdiff
path: root/includes/XmlTypeCheck.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/XmlTypeCheck.php')
-rw-r--r--includes/XmlTypeCheck.php57
1 files changed, 54 insertions, 3 deletions
diff --git a/includes/XmlTypeCheck.php b/includes/XmlTypeCheck.php
index eb98a4ad..aca857e9 100644
--- a/includes/XmlTypeCheck.php
+++ b/includes/XmlTypeCheck.php
@@ -40,6 +40,23 @@ class XmlTypeCheck {
public $rootElement = '';
/**
+ * A stack of strings containing the data of each xml element as it's processed. Append
+ * data to the top string of the stack, then pop off the string and process it when the
+ * element is closed.
+ */
+ protected $elementData = array();
+
+ /**
+ * A stack of element names and attributes, as we process them.
+ */
+ protected $elementDataContext = array();
+
+ /**
+ * Current depth of the data stack.
+ */
+ protected $stackDepth = 0;
+
+ /**
* Additional parsing options
*/
private $parserOptions = array(
@@ -51,7 +68,7 @@ class XmlTypeCheck {
* @param callable $filterCallback (optional)
* Function to call to do additional custom validity checks from the
* SAX element handler event. This gives you access to the element
- * namespace, name, and attributes, but not to text contents.
+ * namespace, name, attributes, and text contents.
* Filter should return 'true' to toggle on $this->filterMatch
* @param boolean $isFile (optional) indicates if the first parameter is a
* filename (default, true) or if it is a string (false)
@@ -179,7 +196,12 @@ class XmlTypeCheck {
$this->rootElement = $name;
if ( is_callable( $this->filterCallback ) ) {
- xml_set_element_handler( $parser, array( $this, 'elementOpen' ), false );
+ xml_set_element_handler(
+ $parser,
+ array( $this, 'elementOpen' ),
+ array( $this, 'elementClose' )
+ );
+ xml_set_character_data_handler( $parser, array( $this, 'elementData' ) );
$this->elementOpen( $parser, $name, $attribs );
} else {
// We only need the first open element
@@ -193,7 +215,26 @@ class XmlTypeCheck {
* @param $attribs
*/
private function elementOpen( $parser, $name, $attribs ) {
- if ( call_user_func( $this->filterCallback, $name, $attribs ) ) {
+ $this->elementDataContext[] = array( $name, $attribs );
+ $this->elementData[] = '';
+ $this->stackDepth++;
+ }
+
+ /**
+ * @param $parser
+ * @param $name
+ */
+ private function elementClose( $parser, $name ) {
+ list( $name, $attribs ) = array_pop( $this->elementDataContext );
+ $data = array_pop( $this->elementData );
+ $this->stackDepth--;
+
+ if ( call_user_func(
+ $this->filterCallback,
+ $name,
+ $attribs,
+ $data
+ ) ) {
// Filter hit!
$this->filterMatch = true;
}
@@ -201,6 +242,16 @@ class XmlTypeCheck {
/**
* @param $parser
+ * @param $data
+ */
+ private function elementData( $parser, $data ) {
+ // xml_set_character_data_handler breaks the data on & characters, so
+ // we collect any data here, and we'll run the callback in elementClose
+ $this->elementData[ $this->stackDepth - 1 ] .= trim( $data );
+ }
+
+ /**
+ * @param $parser
* @param $target
* @param $data
*/