Created
July 11, 2012 14:11
-
-
Save pjbeardsley/3090597 to your computer and use it in GitHub Desktop.
fXML.php.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: fXML.php | |
=================================================================== | |
--- fXML.php (revision 71) | |
+++ fXML.php (working copy) | |
@@ -233,17 +233,17 @@ | |
'__sleep' => TRUE, | |
'__toString' => TRUE, | |
'__wakeup' => TRUE, | |
- 'addCustomPrefix' => TRUE, | |
+ 'addCustomPrefix' => TRUE, | |
+ 'find' => TRUE, | |
'getName' => TRUE, | |
'getNamespace' => TRUE, | |
'getPrefix' => TRUE, | |
- 'getText' => TRUE, | |
'offsetExists' => TRUE, | |
'offsetGet' => TRUE, | |
'offsetSet' => TRUE, | |
'offsetUnset' => TRUE, | |
- 'toXML' => TRUE, | |
- 'xpath' => TRUE | |
+ 'text' => TRUE, | |
+ 'xml' => TRUE | |
); | |
if (isset($methods[$name])) { | |
@@ -373,6 +373,86 @@ | |
/** | |
+ * Executes an XPath query on the current element, returning an array of matching elements | |
+ * | |
+ * @param string $path The XPath path to query | |
+ * @param integer $index The 0-based index of a single match to return | |
+ * @return array|string|fXML An array of matching elements, or a string or fXML object if `$first_only` is `TRUE` | |
+ */ | |
+ public function find($path, $index=NULL) | |
+ { | |
+ $result = $this->query($path); | |
+ | |
+ if ($index !== NULL) { | |
+ if (!$result->length) { return NULL; } | |
+ $result = array($result->item($index)); | |
+ | |
+ } else { | |
+ if (!$result->length) { return array(); } | |
+ } | |
+ | |
+ $keys_to_remove = array(); | |
+ $output = array(); | |
+ | |
+ foreach ($result as $element) { | |
+ | |
+ if ($element instanceof DOMElement) { | |
+ $child = new fXML($element); | |
+ $child->__custom_prefixes = $this->__custom_prefixes; | |
+ if ($child->__dom->namespaceURI && $child->__dom->prefix == '') { | |
+ $child->addCustomPrefix('__', $child->__dom->namespaceURI); | |
+ } | |
+ $output[] = $child; | |
+ | |
+ } elseif ($element instanceof DOMCharacterData) { | |
+ $output[] = $element->data; | |
+ | |
+ } elseif ($element instanceof DOMAttr) { | |
+ | |
+ $key = $element->name; | |
+ if ($element->prefix) { | |
+ $key = $element->prefix . ':' . $key; | |
+ } | |
+ | |
+ // We will create an attrname and attrname[0] key for each | |
+ // attribute and if more than one is found we remove the | |
+ // key attrname. If only one is found we remove attrname[0]. | |
+ $key_1 = $key . '[1]'; | |
+ | |
+ if (isset($output[$key_1])) { | |
+ $i = 1; | |
+ while (isset($output[$key . '[' . $i . ']'])) { | |
+ $i++; | |
+ } | |
+ | |
+ // This removes the key without the array index if more than one was found | |
+ unset($output[$key]); | |
+ unset($keys_to_remove[$key_1]); | |
+ | |
+ $key = $key . '[' . $i . ']'; | |
+ | |
+ } else { | |
+ $output[$key_1] = $element->nodeValue; | |
+ $keys_to_remove[$key_1] = TRUE; | |
+ } | |
+ | |
+ $output[$key] = $element->nodeValue; | |
+ } | |
+ } | |
+ | |
+ foreach ($keys_to_remove as $key => $trash) { | |
+ unset($output[$key]); | |
+ } | |
+ | |
+ if ($index !== NULL) { | |
+ return current($output); | |
+ } | |
+ | |
+ return $output; | |
+ } | |
+ | |
+ | |
+ /** | |
* Fixes HTML entities that aren't XML encoded and fixes ISO-8859-1/Windows-1252 encoded content that does not have an encoding attribute | |
* | |
* @param string $xml The XML to fix | |
@@ -466,17 +546,6 @@ | |
/** | |
- * Returns the string text of the current element | |
- * | |
- * @return string The string text of the current element | |
- */ | |
- public function getText() | |
- { | |
- return (string) $this->__dom->textContent; | |
- } | |
- | |
- | |
- /** | |
* Provides functionality for isset() and empty() (required by arrayaccess interface) | |
* | |
* Offsets refers to an attribute name. Attribute may start with a namespace | |
@@ -591,96 +660,54 @@ | |
return $result; | |
} | |
- | |
- | |
+ | |
+ | |
/** | |
- * Returns a well-formed XML string from the current element | |
+ * Returns the text content of the current element, or the first matching xpath result | |
* | |
- * @return string The XML | |
+ * @param string $xpath The xpath query to execute | |
+ * @return string The text value of the current element, or the first matching xpath result | |
*/ | |
- public function toXML() | |
+ public function text($xpath=NULL) | |
{ | |
- return $this->__dom->ownerDocument->saveXML($this->__dom->parentNode === $this->__dom->ownerDocument ? $this->__dom->parentNode : $this->__dom); | |
+ if ($xpath === NULL) { | |
+ return (string) $this->__dom->textContent; | |
+ } | |
+ | |
+ $result = $this->find($xpath, 0); | |
+ if ($result instanceof fXML) { | |
+ return (string) $result->__dom->textContent; | |
+ } | |
+ | |
+ return $result; | |
} | |
/** | |
- * Executes an XPath query on the current element, returning an array of matching elements | |
+ * Returns a well-formed XML string from the current element, or the first matching xpath result | |
* | |
- * @param string $path The XPath path to query | |
- * @param boolean $first_only If only the first match should be returned | |
- * @return array|string|fXML An array of matching elements, or a string or fXML object if `$first_only` is `TRUE` | |
+ * @param string $xpath The xpath query to execute | |
+ * @param boolean $remove_root_tag If the root XML tag should be removed | |
+ * @param boolean :$remove_root_tag | |
+ * @return string The XML | |
*/ | |
- public function xpath($path, $first_only=FALSE) | |
+ public function xml($xpath=NULL, $remove_root_tag=FALSE) | |
{ | |
- $result = $this->query($path); | |
- | |
- if ($first_only) { | |
- if (!$result->length) { return NULL; } | |
- $result = array($result->item(0)); | |
- | |
- } else { | |
- if (!$result->length) { return array(); } | |
+ if (is_bool($xpath)) { | |
+ $remove_root_tag = $xpath; | |
+ $xpath = NULL; | |
} | |
- | |
- $keys_to_remove = array(); | |
- $output = array(); | |
- | |
- foreach ($result as $element) { | |
- | |
- if ($element instanceof DOMElement) { | |
- $child = new fXML($element); | |
- $child->__custom_prefixes = $this->__custom_prefixes; | |
- if ($child->__dom->namespaceURI && $child->__dom->prefix == '') { | |
- $child->addCustomPrefix('__', $child->__dom->namespaceURI); | |
- } | |
- $output[] = $child; | |
- | |
- } elseif ($element instanceof DOMCharacterData) { | |
- $output[] = $element->data; | |
- | |
- } elseif ($element instanceof DOMAttr) { | |
- | |
- $key = $element->name; | |
- if ($element->prefix) { | |
- $key = $element->prefix . ':' . $key; | |
- } | |
- | |
- // We will create an attrname and attrname[0] key for each | |
- // attribute and if more than one is found we remove the | |
- // key attrname. If only one is found we remove attrname[0]. | |
- $key_1 = $key . '[1]'; | |
- | |
- if (isset($output[$key_1])) { | |
- $i = 1; | |
- while (isset($output[$key . '[' . $i . ']'])) { | |
- $i++; | |
- } | |
- | |
- // This removes the key without the array index if more than one was found | |
- unset($output[$key]); | |
- unset($keys_to_remove[$key_1]); | |
- | |
- $key = $key . '[' . $i . ']'; | |
- | |
- } else { | |
- $output[$key_1] = $element->nodeValue; | |
- $keys_to_remove[$key_1] = TRUE; | |
- } | |
- | |
- $output[$key] = $element->nodeValue; | |
- } | |
+ | |
+ if ($xpath !== NULL) { | |
+ return $this->find($xpath, 0)->xml($remove_root_tag); | |
} | |
- | |
- foreach ($keys_to_remove as $key => $trash) { | |
- unset($output[$key]); | |
+ | |
+ $xml = $this->__dom->ownerDocument->saveXML($this->__dom->parentNode === $this->__dom->ownerDocument ? $this->__dom->parentNode : $this->__dom); | |
+ if ($remove_root_tag) { | |
+ $xml = preg_replace('#^<[^>]*?>#', '', $xml); | |
+ $xml = preg_replace('#<\s*/[^>]*>$#', '', $xml); | |
} | |
- | |
- if ($first_only) { | |
- return current($output); | |
- } | |
- | |
- return $output; | |
+ return $xml; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment