diff --git a/src/simplexml_dump.php b/src/simplexml_dump.php
index 3ad21a3..3a0094c 100644
--- a/src/simplexml_dump.php
+++ b/src/simplexml_dump.php
@@ -42,23 +42,23 @@ function simplexml_dump(SimpleXMLElement $sxml, $return=false)
$dom_item = dom_import_simplexml($item);
// To what namespace does this element or attribute belong? Returns array( alias => URI )
- $ns_prefix = $dom_item->prefix;
- $ns_uri = $dom_item->namespaceURI;
+ $item_ns_alias = $dom_item->prefix;
+ $item_ns_uri = $dom_item->namespaceURI;
if ( $dom_item instanceOf DOMAttr )
{
$dump .= $indent . 'Attribute {' . PHP_EOL;
- if ( ! is_null($ns_uri) )
+ if ( ! is_null($item_ns_uri) )
{
- $dump .= $indent . $indent . 'Namespace: \'' . $ns_uri . '\'' . PHP_EOL;
- if ( $ns_prefix == '' )
+ $dump .= $indent . $indent . 'Namespace: \'' . $item_ns_uri . '\'' . PHP_EOL;
+ if ( $item_ns_alias == '' )
{
$dump .= $indent . $indent . '(Default Namespace)' . PHP_EOL;
}
else
{
- $dump .= $indent . $indent . 'Namespace Alias: \'' . $ns_prefix . '\'' . PHP_EOL;
+ $dump .= $indent . $indent . 'Namespace Alias: \'' . $item_ns_alias . '\'' . PHP_EOL;
}
}
@@ -71,16 +71,16 @@ function simplexml_dump(SimpleXMLElement $sxml, $return=false)
{
$dump .= $indent . 'Element {' . PHP_EOL;
- if ( ! is_null($ns_uri) )
+ if ( ! is_null($item_ns_uri) )
{
- $dump .= $indent . $indent . 'Namespace: \'' . $ns_uri . '\'' . PHP_EOL;
- if ( $ns_prefix == '' )
+ $dump .= $indent . $indent . 'Namespace: \'' . $item_ns_uri . '\'' . PHP_EOL;
+ if ( $item_ns_alias == '' )
{
$dump .= $indent . $indent . '(Default Namespace)' . PHP_EOL;
}
else
{
- $dump .= $indent . $indent . 'Namespace Alias: \'' . $ns_prefix . '\'' . PHP_EOL;
+ $dump .= $indent . $indent . 'Namespace Alias: \'' . $item_ns_alias . '\'' . PHP_EOL;
}
}
@@ -93,33 +93,32 @@ function simplexml_dump(SimpleXMLElement $sxml, $return=false)
// This returns all namespaces used by this node and all its descendants,
// whether declared in this node, in its ancestors, or in its descendants
$all_ns = $item->getNamespaces(true);
- // If the default namespace is never declared, it will never show up using the below code
- if ( ! array_key_exists('', $all_ns) )
+ $has_default_namespace = isset($all_ns['']);
+
+ // If the default namespace is never declared, we need to add a dummy entry for it
+ // We also need to handle the odd fact that attributes are never assigned to the default namespace
+ // The spec basically leaves their meaning undefined: https://www.w3.org/TR/xml-names/#defaulting
+ if ( ! in_array(null, $all_ns, true) )
{
- $all_ns[''] = NULL;
+ $all_ns[] = null;
}
-
- foreach ( $all_ns as $ns_alias => $ns_uri )
+
+ // Prioritise "current" namespace by merging into onto the beginning of the list
+ // (it will be added to the beginning and the duplicate entry dropped)
+ $all_ns = array_unique(array_merge(
+ array($item_ns_uri),
+ $all_ns
+ ));
+
+ foreach ( $all_ns as $ns_uri )
{
$children = $item->children($ns_uri);
$attributes = $item->attributes($ns_uri);
-
- // Somewhat confusingly, in the case where a parent element is missing the xmlns declaration,
- // but a descendant adds it, SimpleXML will look ahead and fill $all_ns[''] incorrectly
- if (
- $ns_alias == ''
- &&
- ! is_null($ns_uri)
- &&
- count($children) == 0
- &&
- count($attributes) == 0
- )
+
+ // Don't show children(null) if we have a default namespace defined
+ if ( $has_default_namespace && $ns_uri === null )
{
- // Try looking for a default namespace without a known URI
- $ns_uri = NULL;
- $children = $item->children($ns_uri);
- $attributes = $item->attributes($ns_uri);
+ $children = array();
}
// Don't show zero-counts, as they're not that useful
@@ -128,59 +127,56 @@ function simplexml_dump(SimpleXMLElement $sxml, $return=false)
continue;
}
- $ns_label = (($ns_alias == '') ? 'Default Namespace' : "Namespace $ns_alias");
+ $ns_label = ($ns_uri === null) ? 'Null Namespace' : "Namespace '$ns_uri'";
$dump .= $indent . $indent . 'Content in ' . $ns_label . PHP_EOL;
- if ( ! is_null($ns_uri) )
- {
- $dump .= $indent . $indent . $indent . 'Namespace URI: \'' . $ns_uri . '\'' . PHP_EOL;
- }
-
- // Count occurrence of child element names, rather than listing them all out
- $child_names = array();
- foreach ( $children as $sx_child )
- {
- // Below is a rather clunky way of saying $child_names[ $sx_child->getName() ]++;
- // which avoids Notices about unset array keys
- $child_node_name = $sx_child->getName();
- if ( array_key_exists($child_node_name, $child_names) )
- {
- $child_names[$child_node_name]++;
- }
- else
- {
- $child_names[$child_node_name] = 1;
- }
- }
- ksort($child_names);
- $child_name_output = array();
- foreach ( $child_names as $name => $count )
- {
- $child_name_output[] = "$count '$name'";
- }
-
- $dump .= $indent . $indent . $indent . 'Children: ' . count($children);
- // Don't output a trailing " - " if there are no children
if ( count($children) > 0 )
{
+ // Count occurrence of child element names, rather than listing them all out
+ $child_names = array();
+ foreach ( $children as $sx_child )
+ {
+ // Below is a rather clunky way of saying $child_names[ $sx_child->getName() ]++;
+ // which avoids Notices about unset array keys
+ $child_node_name = $sx_child->getName();
+ if ( array_key_exists($child_node_name, $child_names) )
+ {
+ $child_names[$child_node_name]++;
+ }
+ else
+ {
+ $child_names[$child_node_name] = 1;
+ }
+ }
+ ksort($child_names);
+ $child_name_output = array();
+ foreach ( $child_names as $name => $count )
+ {
+ $child_name_output[] = "$count '$name'";
+ }
+
+ $dump .= $indent . $indent . $indent . 'Children: ' . count($children);
$dump .= ' - ' . implode(', ', $child_name_output);
+ $dump .= PHP_EOL;
}
- $dump .= PHP_EOL;
-
- // Attributes can't be duplicated, but I'm going to put them in alphabetical order
- $attribute_names = array();
- foreach ( $attributes as $sx_attribute )
- {
- $attribute_names[] = "'" . $sx_attribute->getName() . "'";
- }
- ksort($attribute_names);
- $dump .= $indent . $indent . $indent . 'Attributes: ' . count($attributes);
- // Don't output a trailing " - " if there are no attributes
+
if ( count($attributes) > 0 )
{
- $dump .= ' - ' . implode(', ', $attribute_names);
+ // Attributes can't be duplicated, but I'm going to put them in alphabetical order
+ $attribute_names = array();
+ foreach ( $attributes as $sx_attribute )
+ {
+ $attribute_names[] = "'" . $sx_attribute->getName() . "'";
+ }
+ ksort($attribute_names);
+ $dump .= $indent . $indent . $indent . 'Attributes: ' . count($attributes);
+ // Don't output a trailing " - " if there are no attributes
+ if ( count($attributes) > 0 )
+ {
+ $dump .= ' - ' . implode(', ', $attribute_names);
+ }
+ $dump .= PHP_EOL;
}
- $dump .= PHP_EOL;
}
$dump .= $indent . '}' . PHP_EOL;
diff --git a/src/simplexml_tree.php b/src/simplexml_tree.php
index a80a865..6968e49 100644
--- a/src/simplexml_tree.php
+++ b/src/simplexml_tree.php
@@ -145,32 +145,44 @@ function _simplexml_tree_recursively_process_node($item, $depth, $include_string
// This returns all namespaces used by this node and all its descendants,
// whether declared in this node, in its ancestors, or in its descendants
$all_ns = $item->getNamespaces(true);
- // If the default namespace is never declared, it will never show up using the below code
- if ( ! array_key_exists('', $all_ns) )
+ $has_default_namespace = isset($all_ns['']);
+
+ // If the default namespace is never declared, we need to add a dummy entry for it
+ // We also need to handle the odd fact that attributes are never assigned to the default namespace
+ // The spec basically leaves their meaning undefined: https://www.w3.org/TR/xml-names/#defaulting
+ if ( ! in_array(null, $all_ns, true) )
{
- $all_ns[''] = NULL;
+ $all_ns[] = null;
}
// Prioritise "current" namespace by merging into onto the beginning of the list
- // (it will be added to the beginning and the duplicate entry dropped)
- $all_ns = array_merge(
- array($item_ns_prefix => $item_ns_uri),
+ // (it will be added to the beginning and the duplicate entry dropped)
+ $all_ns = array_unique(array_merge(
+ array($item_ns_uri),
$all_ns
- );
+ ));
- foreach ( $all_ns as $ns_alias => $ns_uri )
+ foreach ( $all_ns as $ns_uri )
{
- $children = $item->children($ns_alias, true);
- $attributes = $item->attributes($ns_alias, true);
-
+ $children = $item->children($ns_uri);
+ $attributes = $item->attributes($ns_uri);
+
+ // Don't show children(null) if we have a default namespace defined
+ if ( $has_default_namespace && $ns_uri === null )
+ {
+ $children = array();
+ }
+
// If things are in the current namespace, display them a bit differently
$is_current_namespace = ( $ns_uri == $item_ns_uri );
+ $force_attribute_namespace = ($ns_uri === null && $item_ns_uri !== null);
+
$ns_uri_quoted = (strlen($ns_uri) == 0 ? 'null' : "'$ns_uri'");
if ( count($attributes) > 0 )
{
- if ( ! $is_current_namespace )
+ if ( ! $is_current_namespace || $force_attribute_namespace )
{
$dump .= str_repeat($indent, $depth)
. "->attributes($ns_uri_quoted)" . PHP_EOL;
@@ -179,7 +191,7 @@ function _simplexml_tree_recursively_process_node($item, $depth, $include_string
foreach ( $attributes as $sx_attribute )
{
// Output the attribute
- if ( $is_current_namespace )
+ if ( $is_current_namespace && ! $force_attribute_namespace )
{
// In current namespace
// e.g. ['attribName']
diff --git a/tests/dump-output/basic b/tests/dump-output/basic
index 510fe3b..a7359d1 100644
--- a/tests/dump-output/basic
+++ b/tests/dump-output/basic
@@ -5,8 +5,7 @@ SimpleXML object (1 item)
String Content: '
'
- Content in Default Namespace
+ Content in Null Namespace
Children: 1 - 1 'movie'
- Attributes: 0
}
]
diff --git a/tests/dump-output/basic-default-ns b/tests/dump-output/basic-default-ns
index cf178ad..109c6a7 100644
--- a/tests/dump-output/basic-default-ns
+++ b/tests/dump-output/basic-default-ns
@@ -7,9 +7,7 @@ SimpleXML object (1 item)
String Content: '
'
- Content in Default Namespace
- Namespace URI: 'https://github.com/IMSoP/simplexml_debug'
+ Content in Namespace 'https://github.com/IMSoP/simplexml_debug'
Children: 1 - 1 'movie'
- Attributes: 0
}
]
diff --git a/tests/dump-output/basic-multiple-ns b/tests/dump-output/basic-multiple-ns
new file mode 100644
index 0000000..2f7a94d
--- /dev/null
+++ b/tests/dump-output/basic-multiple-ns
@@ -0,0 +1,13 @@
+SimpleXML object (1 item)
+[
+ Element {
+ Namespace: 'https://github.com/IMSoP/simplexml_debug#movies'
+ Namespace Alias: 'movies'
+ Name: 'movies'
+ String Content: '
+
+'
+ Content in Namespace 'https://github.com/IMSoP/simplexml_debug#movies'
+ Children: 1 - 1 'movie'
+ }
+]
diff --git a/tests/dump-output/basic-ns b/tests/dump-output/basic-ns
index 34de153..1d399a7 100644
--- a/tests/dump-output/basic-ns
+++ b/tests/dump-output/basic-ns
@@ -1,13 +1,13 @@
SimpleXML object (1 item)
[
Element {
+ Namespace: 'https://github.com/IMSoP/simplexml_debug'
+ Namespace Alias: 'test'
Name: 'movies'
String Content: '
'
- Content in Namespace test
- Namespace URI: 'https://github.com/IMSoP/simplexml_debug'
+ Content in Namespace 'https://github.com/IMSoP/simplexml_debug'
Children: 1 - 1 'movie'
- Attributes: 0
}
]
diff --git a/tests/dump-output/issue-11 b/tests/dump-output/issue-11
index 8a77221..77a71e5 100644
--- a/tests/dump-output/issue-11
+++ b/tests/dump-output/issue-11
@@ -3,9 +3,7 @@ SimpleXML object (1 item)
Element {
Name: 'notinnamespace'
String Content: ''
- Content in Namespace test
- Namespace URI: 'http://example.com'
- Children: 0
+ Content in Namespace 'http://example.com'
Attributes: 1 - 'isinnamespace'
}
]
diff --git a/tests/dump-output/issue-3 b/tests/dump-output/issue-3
new file mode 100644
index 0000000..9ea7468
--- /dev/null
+++ b/tests/dump-output/issue-3
@@ -0,0 +1,15 @@
+SimpleXML object (1 item)
+[
+ Element {
+ Namespace: 'http://example.com'
+ (Default Namespace)
+ Name: 'Foo'
+ String Content: '
+
+'
+ Content in Namespace 'http://example.com'
+ Children: 1 - 1 'MaskingChildElement'
+ Content in Null Namespace
+ Attributes: 1 - 'InvisibleAttribute'
+ }
+]
diff --git a/tests/dump-output/soap b/tests/dump-output/soap
index e1e31a2..8c846e3 100644
--- a/tests/dump-output/soap
+++ b/tests/dump-output/soap
@@ -8,9 +8,7 @@ SimpleXML object (1 item)
'
- Content in Namespace soap
- Namespace URI: 'http://schemas.xmlsoap.org/soap/envelope/'
+ Content in Namespace 'http://schemas.xmlsoap.org/soap/envelope/'
Children: 2 - 1 'Body', 1 'Header'
- Attributes: 0
}
]
diff --git a/tests/input/basic-default-ns.xml b/tests/input/basic-default-ns.xml
index ce2b9df..68507cc 100644
--- a/tests/input/basic-default-ns.xml
+++ b/tests/input/basic-default-ns.xml
@@ -23,4 +23,4 @@
7
5
-
\ No newline at end of file
+
diff --git a/tests/input/basic-multiple-ns.xml b/tests/input/basic-multiple-ns.xml
new file mode 100644
index 0000000..c1870ff
--- /dev/null
+++ b/tests/input/basic-multiple-ns.xml
@@ -0,0 +1,26 @@
+
+
+
+ PHP: Behind the Parser
+
+
+ Ms. Coder
+ Onlivia Actora
+
+
+ Mr. Coder
+ El ActÓr
+
+
+
+ So, this language. It's like, a programming language.
+ Or is it a scripting language? All is revealed in this
+ thrilling horror spoof of a documentary.
+
+
+ PHP solves all my web problems
+
+ 7
+ 5
+
+
diff --git a/tests/input/basic-ns.xml b/tests/input/basic-ns.xml
index 9b3afbd..f86c432 100644
--- a/tests/input/basic-ns.xml
+++ b/tests/input/basic-ns.xml
@@ -1,5 +1,5 @@
-
+
PHP: Behind the Parser
@@ -20,7 +20,7 @@
PHP solves all my web problems
- 7
- 5
+ 7
+ 5
-
\ No newline at end of file
+
diff --git a/tests/input/basic.xml b/tests/input/basic.xml
index a1d4621..2246039 100644
--- a/tests/input/basic.xml
+++ b/tests/input/basic.xml
@@ -23,4 +23,4 @@
7
5
-
\ No newline at end of file
+
diff --git a/tests/input/issue-3.xml b/tests/input/issue-3.xml
new file mode 100644
index 0000000..a94a0b7
--- /dev/null
+++ b/tests/input/issue-3.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/tests/tree-output/basic-default-ns b/tests/tree-output/basic-default-ns
index 67aa4c3..88518ae 100644
--- a/tests/tree-output/basic-default-ns
+++ b/tests/tree-output/basic-default-ns
@@ -14,6 +14,8 @@ SimpleXML object (1 item)
->great-lines[0]
->line[0]
->rating[0]
- ['type']
+ ->attributes(null)
+ ->type
->rating[1]
- ['type']
+ ->attributes(null)
+ ->type
diff --git a/tests/tree-output/basic-multiple-ns b/tests/tree-output/basic-multiple-ns
new file mode 100644
index 0000000..faef5af
--- /dev/null
+++ b/tests/tree-output/basic-multiple-ns
@@ -0,0 +1,22 @@
+SimpleXML object (1 item)
+[0] //
+ ->children('https://github.com/IMSoP/simplexml_debug#movies')
+ ->movie[0]
+ ->title[0]
+ ->characters[0]
+ ->character[0]
+ ->name[0]
+ ->actor[0]
+ ->character[1]
+ ->name[0]
+ ->actor[0]
+ ->plot[0]
+ ->children('https://github.com/IMSoP/simplexml_debug#reviews')
+ ->great-lines[0]
+ ->line[0]
+ ->rating[0]
+ ->attributes(null)
+ ->type
+ ->rating[1]
+ ->attributes(null)
+ ->type
diff --git a/tests/tree-output/basic-ns b/tests/tree-output/basic-ns
index 88518ae..a459a21 100644
--- a/tests/tree-output/basic-ns
+++ b/tests/tree-output/basic-ns
@@ -1,5 +1,5 @@
SimpleXML object (1 item)
-[0] //
+[0] //
->children('https://github.com/IMSoP/simplexml_debug')
->movie[0]
->title[0]
@@ -14,8 +14,6 @@ SimpleXML object (1 item)
->great-lines[0]
->line[0]
->rating[0]
- ->attributes(null)
- ->type
+ ['type']
->rating[1]
- ->attributes(null)
- ->type
+ ['type']
diff --git a/tests/tree-output/issue-3 b/tests/tree-output/issue-3
new file mode 100644
index 0000000..fe1fa55
--- /dev/null
+++ b/tests/tree-output/issue-3
@@ -0,0 +1,5 @@
+SimpleXML object (1 item)
+[0] //
+ ['InvisibleAttribute']
+ ->children('http://example.com')
+ ->MaskingChildElement[0]