Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 71 additions & 75 deletions src/simplexml_dump.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand All @@ -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;
}
}

Expand All @@ -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
Expand All @@ -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;
Expand Down
38 changes: 25 additions & 13 deletions src/simplexml_tree.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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']
Expand Down
3 changes: 1 addition & 2 deletions tests/dump-output/basic
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ SimpleXML object (1 item)
String Content: '

'
Content in Default Namespace
Content in Null Namespace
Children: 1 - 1 'movie'
Attributes: 0
}
]
4 changes: 1 addition & 3 deletions tests/dump-output/basic-default-ns
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
]
13 changes: 13 additions & 0 deletions tests/dump-output/basic-multiple-ns
Original file line number Diff line number Diff line change
@@ -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'
}
]
6 changes: 3 additions & 3 deletions tests/dump-output/basic-ns
Original file line number Diff line number Diff line change
@@ -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
}
]
4 changes: 1 addition & 3 deletions tests/dump-output/issue-11
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
]
15 changes: 15 additions & 0 deletions tests/dump-output/issue-3
Original file line number Diff line number Diff line change
@@ -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'
}
]
4 changes: 1 addition & 3 deletions tests/dump-output/soap
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
]
2 changes: 1 addition & 1 deletion tests/input/basic-default-ns.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
<rating type="thumbs">7</rating>
<rating type="stars">5</rating>
</movie>
</movies>
</movies>
26 changes: 26 additions & 0 deletions tests/input/basic-multiple-ns.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" ?>
<movies:movies xmlns:movies="https://github.com/IMSoP/simplexml_debug#movies" xmlns:reviews="https://github.com/IMSoP/simplexml_debug#reviews">
<movies:movie>
<movies:title>PHP: Behind the Parser</movies:title>
<movies:characters>
<movies:character>
<movies:name>Ms. Coder</movies:name>
<movies:actor>Onlivia Actora</movies:actor>
</movies:character>
<movies:character>
<movies:name>Mr. Coder</movies:name>
<movies:actor>El Act&#211;r</movies:actor>
</movies:character>
</movies:characters>
<movies:plot>
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.
</movies:plot>
<reviews:great-lines>
<reviews:line>PHP solves all my web problems</reviews:line>
</reviews:great-lines>
<reviews:rating type="thumbs">7</reviews:rating>
<reviews:rating type="stars">5</reviews:rating>
</movies:movie>
</movies:movies>
Loading