Skip to content

Instantly share code, notes, and snippets.

@pjbeardsley
Created July 11, 2012 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pjbeardsley/3090597 to your computer and use it in GitHub Desktop.
Save pjbeardsley/3090597 to your computer and use it in GitHub Desktop.
fXML.php.patch
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