Skip to content

Commit

Permalink
Fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
JackieDo committed Nov 28, 2018
1 parent 9e24201 commit f0a0c22
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 105 deletions.
96 changes: 58 additions & 38 deletions src/Xml2Array.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ protected function loadXml($inputXml)
$this->xml = new DOMDocument($this->config['version'], $this->config['encoding']);

if (is_string($inputXml)) {
$this->xml->loadXML($inputXml);
$parse = @$this->xml->loadXML($inputXml);

if ($parse === false) {
throw new DOMException('Error parsing XML string, input is not a well-formed XML string.');
}
} elseif ($inputXml instanceof SimpleXMLElement) {
$this->xml->loadXML($inputXml->asXML());
} elseif ($inputXml instanceof DOMDocument) {
Expand All @@ -215,21 +219,16 @@ protected function parseNode(DOMNode $node)

switch ($node->nodeType) {
case XML_CDATA_SECTION_NODE:
$output[$this->config['cdataKey']] = trim($node->textContent);
$output[$this->config['cdataKey']] = $this->normalizeTextContent($node->textContent);
break;

case XML_TEXT_NODE:
$output = trim(preg_replace([
'/\n+\s+/',
'/\r+\s+/',
'/\n+\t+/',
'/\r+\t+/'
], ' ', $node->textContent));
$output = $this->normalizeTextContent($node->textContent);
break;

case XML_ELEMENT_NODE:
$output = $this->parseChildNodes($node, $output);
$output = $this->normalizeValues($output);
$output = $this->normalizeNodeValues($output);
$output = $this->collectAttributes($node, $output);
break;
}
Expand All @@ -247,32 +246,36 @@ protected function parseNode(DOMNode $node)
*/
protected function parseChildNodes(DOMNode $node, $output)
{
if ($node->childNodes->length == 1) {
if (!empty($output)) {
$output[$this->config['valueKey']] = $this->parseNode($node->firstChild);
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_CDATA_SECTION_NODE) {
if (!is_array($output)) {
if (!empty($output)) {
$output = [$this->config['valueKey'] => $output];
} else {
$output = [];
}
}

$output[$this->config['cdataKey']] = $this->normalizeTextContent($child->textContent);
} else {
$output = $this->parseNode($node->firstChild);
}
} else {
foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_CDATA_SECTION_NODE) {
$output[$this->config['cdataKey']] = trim($child->textContent);
} else {
$value = $this->parseNode($child);
$value = $this->parseNode($child);

if ($child->nodeType == XML_TEXT_NODE) {
if ($value != '') {
if ($child->nodeType == XML_TEXT_NODE) {
if ($value != '') {
if (!empty($output)) {
$output[$this->config['valueKey']] = $value;
} else {
$output = $value;
}
} else {
$nodeName = $child->nodeName;

if (!isset($output[$nodeName])) {
$output[$nodeName] = [];
}
}
} else {
$nodeName = $child->nodeName;

$output[$nodeName][] = $value;
if (!isset($output[$nodeName])) {
$output[$nodeName] = [];
}

$output[$nodeName][] = $value;
}
}
}
Expand All @@ -281,32 +284,49 @@ protected function parseChildNodes(DOMNode $node, $output)
}

/**
* Normalize values
* Clean text content of text node
*
* @param string $textContent
*
* @return string
*/
protected function normalizeTextContent($textContent)
{
return trim(preg_replace([
'/\n+\s+/',
'/\r+\s+/',
'/\n+\t+/',
'/\r+\t+/'
], ' ', $textContent));
}

/**
* Normalize values of node
*
* @param mixed $output
* @param mixed $values
*
* @return mixed
*/
protected function normalizeValues($output)
protected function normalizeNodeValues($values)
{
if (is_array($output)) {
if (is_array($values)) {
// if only one node of its kind, assign it directly instead if array($value);
foreach ($output as $key => $value) {
foreach ($values as $key => $value) {
if (is_array($value) && count($value) === 1) {
$keyName = array_keys($value)[0];

if (is_numeric($keyName)) {
$output[$key] = $value[$keyName];
$values[$key] = $value[$keyName];
}
}
}

if (empty($output)) {
$output = '';
if (empty($values)) {
$values = '';
}
}

return $output;
return $values;
}

/**
Expand Down
68 changes: 57 additions & 11 deletions tests/Array2XmlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,29 +59,75 @@ class Array2XmlTest extends TestCase
];

/**
* Expected xml string
* Throw DOMException when there are more than one root node
*
* @var string
* @test
*
* @return void
*/
protected $expected_xml_string = '<?xml version="1.0" encoding="UTF-8"?><root_node><tag>Example tag</tag><attribute_tag description="This is a tag with attribute">Another tag with attributes</attribute_tag><cdata_section><![CDATA[This is CDATA section]]></cdata_section><tag_with_subtag><sub_tag>Sub tag 1</sub_tag><sub_tag>Sub tag 2</sub_tag></tag_with_subtag><mixed_section>Hello<![CDATA[This is another CDATA section]]><section id="sec_1">Section number 1</section><section id="sec_2">Section number 2</section><section id="sec_3">Section number 3</section></mixed_section><example:with_namespace xmlns:example="http://example.com"><example:sub>Content</example:sub></example:with_namespace></root_node>';
public function throw_dom_exception_when_there_are_more_than_one_root_node()
{
$this->expectException(DOMException::class);
$this->expectExceptionMessage('XML documents are allowed only one root element. Wrap your elements in a key or set the `rootElement` parameter in the configuration.');

$process = Array2Xml::convert([
'root' => 'content',
'another_root' => 'Another content'
]);
}

/**
* Convert array to xml string
* Throw DOMException when node name is invalid
*
* @test
*
* @return void
*/
public function convert_array_to_xml_string()
public function throw_dom_exception_when_node_name_is_invalid()
{
$dom = new DOMDocument;
$dom->loadXML($this->expected_xml_string);
$this->expectException(DOMException::class);
$this->expectExceptionMessage('Invalid character in the tag name being generated: 0');

$process = Array2Xml::convert(['content']);
}

/**
* Throw DOMException when attribute name is invalid
*
* @test
*
* @return void
*/
public function throw_dom_exception_when_attaribute_name_is_invalid()
{
$this->expectException(DOMException::class);
$this->expectExceptionMessage('Invalid character in the attribute name being generated: invalid attribute');

$process = Array2Xml::convert([
'root' => [
'sub' => [
'@attributes' => [
'invalid attribute' => 'Attribute value'
]
]
]
]);
}

$this->assertSame($dom->saveXML(), Array2Xml::convert($this->input_array)->toXml());
/**
* Convert array to XML string
*
* @test
*
* @return void
*/
public function convert_array_to_xml_string()
{
$this->assertXmlStringEqualsXmlFile(__DIR__ . '/resources/example.xml', Array2Xml::convert($this->input_array)->toXml());
}

/**
* Convert array to dom
* Convert array to DOM
*
* @test
*
Expand All @@ -90,8 +136,8 @@ public function convert_array_to_xml_string()
public function convert_array_to_dom()
{
$dom = new DOMDocument;
$dom->loadXML($this->expected_xml_string);
$dom->loadXML(file_get_contents(__DIR__ . '/resources/example.xml'));

$this->assertSame($dom->saveXML(), Array2Xml::convert($this->input_array)->toDom()->saveXML());
$this->assertEquals($dom, Array2Xml::convert($this->input_array)->toDom());
}
}
Loading

0 comments on commit f0a0c22

Please sign in to comment.