Skip to content

Commit

Permalink
Merge pull request #33 from danhunsaker/feature/xml-attributes
Browse files Browse the repository at this point in the history
Added XML Attribute and Namespace Support
  • Loading branch information
nathanmac authored Sep 1, 2016
2 parents 88c0522 + d55579a commit ed9db12
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 13 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,9 @@ $parsed = $parser->json('
$parser = new Parser();
$parsed = $parser->xml('
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<message>
<xml xmlns:ns="http://example.com/xmlns">
<message status="sent">
<ns:meta hint="created">Created 5 minutes ago</ns:meta>
<to>Jack Smith</to>
<from>Jane Doe</from>
<subject>Hello World</subject>
Expand Down
14 changes: 9 additions & 5 deletions src/Formats/MSGPack.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ public function parse($payload)
if (function_exists('msgpack_unpack')) {
if ($payload) {
$prevHandler = set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) {
throw new ParserException('Failed To Parse MSGPack'); // @codeCoverageIgnore
throw new \Exception($errstr); // @codeCoverageIgnore
});

$msg = msgpack_unpack(trim($payload));
if ( ! $msg) {
set_error_handler($prevHandler); // @codeCoverageIgnore
throw new ParserException('Failed To Parse MSGPack'); // @codeCoverageIgnore
try {
$msg = msgpack_unpack(trim($payload));
if ( ! $msg) {
throw new \Exception('Unknown error'); // @codeCoverageIgnore
}
} catch (\Exception $e) {
set_error_handler($prevHandler);
throw new ParserException('Failed To Parse MSGPack - ' . $e->getMessage());
}

set_error_handler($prevHandler);
Expand Down
44 changes: 38 additions & 6 deletions src/Formats/XML.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,49 @@ public function parse($payload)
if ($payload) {
try {
$xml = simplexml_load_string($payload, 'SimpleXMLElement', LIBXML_NOCDATA);

// Fix for empty values in XML
$json = json_encode((array) $xml);
$json = str_replace(':{}', ':null', $json);
$json = str_replace(':[]', ':null', $json);
return json_decode($json, 1); // Work around to accept xml input
$ns = ['' => null] + $xml->getDocNamespaces(true);
return $this->recursive_parse($xml, $ns);
} catch (\Exception $ex) {
throw new ParserException('Failed To Parse XML');
}
}

return [];
}

protected function recursive_parse($xml, $ns)
{
$result = (string) $xml;

foreach ($ns as $nsName => $nsUri) {
foreach ($xml->attributes($nsUri) as $attName => $attValue) {
if ( ! empty($nsName)) {
$attName = "{$nsName}:{$attName}";
}

$result["@{$attName}"] = $attValue;
}

foreach ($xml->children($nsUri) as $childName => $child) {
if ( ! empty($nsName)) {
$childName = "{$nsName}:{$childName}";
}

$child = $this->recursive_parse($child, $ns);

if (isset($result[$childName])) {
if (is_numeric(key($result[$childName]))) {
$result[$childName][] = $child;
} else {
$temp = $result[$childName];
$result[$childName] = [$temp, $child];
}
} else {
$result[$childName] = $child;
}
}
}

return $result;
}
}
22 changes: 22 additions & 0 deletions tests/XMLTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public function parse_auto_detect_xml_data()

$this->assertEquals(['status' => 123, 'message' => 'hello world'], $parser->payload());
}

/** @test */
public function parse_auto_detect_xml_data_define_content_type_as_param()
{
Expand All @@ -81,6 +82,27 @@ public function parser_validates_xml_data()
$this->assertEquals(['status' => 123, 'message' => 'hello world'], $parser->xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><xml><status>123</status><message>hello world</message></xml>"));
}

/** @test */
public function parser_validates_xml_data_with_attribute()
{
$parser = new Parser();
$this->assertEquals(['status' => 123, 'message' => 'hello world', '@name' => 'root'], $parser->xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><xml name=\"root\"><status>123</status><message>hello world</message></xml>"));
}

/** @test */
public function parser_validates_xml_data_with_namespace()
{
$parser = new Parser();
$this->assertEquals(['status' => 123, 'ns:message' => 'hello world'], $parser->xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><xml xmlns:ns=\"data:namespace\"><status>123</status><ns:message>hello world</ns:message></xml>"));
}

/** @test */
public function parser_validates_xml_data_with_attribute_and_namespace()
{
$parser = new Parser();
$this->assertEquals(['status' => 123, 'ns:message' => 'hello world', '@name' => 'root'], $parser->xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><xml name=\"root\" xmlns:ns=\"data:namespace\"><status>123</status><ns:message>hello world</ns:message></xml>"));
}

/** @test */
public function parser_empty_xml_data()
{
Expand Down

0 comments on commit ed9db12

Please sign in to comment.