diff --git a/src/FeedIo/Formatter/XmlFormatter.php b/src/FeedIo/Formatter/XmlFormatter.php
index a9b0921d..409250d6 100644
--- a/src/FeedIo/Formatter/XmlFormatter.php
+++ b/src/FeedIo/Formatter/XmlFormatter.php
@@ -95,7 +95,7 @@ public function getAllRules(RuleSet $ruleSet, NodeInterface $node) : iterable
$rules = $ruleSet->getRules();
$optionalFields = $node->listElements();
foreach ($optionalFields as $optionalField) {
- $rules[] = new OptionalField($optionalField);
+ $rules[$optionalField] = new OptionalField($optionalField);
}
return $rules;
diff --git a/src/FeedIo/Rule/OptionalField.php b/src/FeedIo/Rule/OptionalField.php
index 9d4a6bfb..b06217ad 100644
--- a/src/FeedIo/Rule/OptionalField.php
+++ b/src/FeedIo/Rule/OptionalField.php
@@ -131,13 +131,23 @@ protected function hasValue(NodeInterface $node) : bool
*/
protected function addElement(\DomDocument $document, \DOMElement $rootElement, NodeInterface $node) : void
{
- $domElement = $document->createElement($this->getNodeName());
+ $addedElementsCount = 0;
+
if ($node instanceof ElementsAwareInterface) {
foreach ($node->getElementIterator($this->getNodeName()) as $element) {
+ $domElement = $document->createElement($this->getNodeName());
+
$this->buildDomElement($domElement, $element);
+
+ $rootElement->appendChild($domElement);
+
+ $addedElementsCount++;
}
}
- $rootElement->appendChild($domElement);
+ if (! $addedElementsCount) {
+ // add an implicit empty element if the node had no elements matching this rule
+ $rootElement->appendChild($document->createElement($this->getNodeName()));
+ }
}
}
diff --git a/tests/FeedIo/FormatterTest.php b/tests/FeedIo/FormatterTest.php
index f3a97432..07038f43 100644
--- a/tests/FeedIo/FormatterTest.php
+++ b/tests/FeedIo/FormatterTest.php
@@ -67,11 +67,13 @@ public function testGetAllRules()
$item = new Item();
$item->set('title', 'the title');
$item->set('description', 'the description');
+ $item->set('custom', 'a custom value');
+ $item->set('custom', 'another custom value');
$rules = $this->object->getAllRules(new RuleSet(), $item);
- $this->assertCount(2, $rules);
+ $this->assertCount(3, $rules);
- $ruleNames = array('title', 'description');
+ $ruleNames = array('title', 'description', 'custom');
foreach ($rules as $rule) {
$this->assertEquals(current($ruleNames), $rule->getNodeName());
next($ruleNames);
diff --git a/tests/FeedIo/Rule/OptionalFieldTest.php b/tests/FeedIo/Rule/OptionalFieldTest.php
index cd1a3e9e..0e707507 100644
--- a/tests/FeedIo/Rule/OptionalFieldTest.php
+++ b/tests/FeedIo/Rule/OptionalFieldTest.php
@@ -37,9 +37,9 @@ public function testSetProperty()
$this->assertTrue($item->hasElement('test'));
$this->assertEquals('a test value', $item->getValue('test'));
-
+
$itemElements = $item->getElementIterator('test');
-
+
$count = 0;
/** @var Element $itemElement */
foreach ($itemElements as $itemElement) {
@@ -172,6 +172,26 @@ public function testCreateElementWithAttributes()
$this->assertTrue($domElement->hasAttribute('foo'));
}
+ public function testCreateMultipleElements()
+ {
+ $item = new Item();
+ $item->set('default', 'first value');
+ $item->set('default', 'second value');
+
+ $document = new \DOMDocument();
+ $rootElement = $document->createElement('feed');
+
+ $this->object->apply($document, $rootElement, $item);
+
+ $this->assertEquals(2, $rootElement->childNodes->count());
+
+ $this->assertEquals('default', $rootElement->childNodes->item(0)->nodeName);
+ $this->assertEquals('first value', $rootElement->childNodes->item(0)->nodeValue);
+
+ $this->assertEquals('default', $rootElement->childNodes->item(1)->nodeName);
+ $this->assertEquals('second value', $rootElement->childNodes->item(1)->nodeValue);
+ }
+
public function testDontCreateElement()
{
$item = new Item();
diff --git a/tests/FeedIo/StandardFormatter/FormatterTestAbstract.php b/tests/FeedIo/StandardFormatter/FormatterTestAbstract.php
index 12642911..d348045c 100644
--- a/tests/FeedIo/StandardFormatter/FormatterTestAbstract.php
+++ b/tests/FeedIo/StandardFormatter/FormatterTestAbstract.php
@@ -60,6 +60,9 @@ public function testFormat()
$item->setLink('http://localhost/item/1');
$item->set('author', 'name@domain.tld');
$item->addCategory($category);
+ $item->set('custom', 'a sample value');
+ $item->set('custom', 'another sample value');
+
$feed->add($item);
$formatter = new XmlFormatter($this->standard);
diff --git a/tests/samples/expected-atom.xml b/tests/samples/expected-atom.xml
index f5b7e806..64f904a3 100644
--- a/tests/samples/expected-atom.xml
+++ b/tests/samples/expected-atom.xml
@@ -14,7 +14,9 @@
http://localhost/item/1
2014-12-01T00:00:00+00:00
- A great description
name@domain.tld
+ A great description
+ a sample value
+ another sample value
diff --git a/tests/samples/rss/expected-rss.xml b/tests/samples/rss/expected-rss.xml
index 1fd1f0c5..93df56ec 100644
--- a/tests/samples/rss/expected-rss.xml
+++ b/tests/samples/rss/expected-rss.xml
@@ -14,8 +14,10 @@
A great description
Mon, 01 Dec 2014 00:00:00 +0000
sample
- http://localhost/item/1
name@domain.tld
+ http://localhost/item/1
+ a sample value
+ another sample value