2

I am using simple PHP script which creates XML.

XML looks like:

<?xml version="1.0" encoding="UTF-8"?>
<article id="1"><published>05/01/2015 04:32:36</published><author position="writer">John Stewart</author>

Nothing special right? Yea and after that i write another PHP script which try to add second article to XML.

The code looks like:

$dom=new DOMDocument();

$dom->load("articles.xml");

$article=$dom->createElement("article");
$article->setAttribute("id", 2);
$published=$dom->CreateElement("published");
$publishedDate=$dom->createTextNode(date("d/m/Y h:i:s", strtotime("tomorrow")));
$published->appendChild($publishedDate);
$article->appendChild($published);
$author=$dom->createElement("author");
$author->setAttribute("position", "writer");
$authorName=$dom->createTextNode("Ivan Dimov");
$author->appendChild($authorName);
$article->appendChild($author);
$dom->documentElement->appendChild($article);

$dom->save("articles.xml");

I'm probably blind because this code looks good for me, but generate XML looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<article id="1"><published>05/01/2015 04:32:36</published><author position="writer">John Stewart</author>
<article id="2"><published>06/01/2015 12:00:00</published><author position="writer">Ivan Dimov</author></article></article>

So in general, it adds new <article> before it end old one , and now XML have twice end article tag at the end.

Can someone help me to find the correct way how to do that? If you find a bit time to explain me what was wrong it would be awesome.

Thank you all for reading

2
  • 1
    Note you have article and articleS tags at the end. The second one has a trailing s. Commented Jan 5, 2015 at 15:29
  • Really good point @fedorqui , anyway now i changed it in XML file before edit. But i still need to change the way how this PHP edit XML becuase now i have </article> at the end twice Commented Jan 5, 2015 at 15:35

2 Answers 2

2

Since you had that article/articles error in your original post, could it be that you've changed an existing code example that worked on a document like

<articles>
  <article id="1">...</article>
...
  <article id="n">...</article>
</articles>

?
According to the xml specification an xml document has exactly one document element, not more.

<?php
$doc=new DOMDocument();
$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;
$doc->loadxml( getData() );
$article = newArticle($doc);
$doc->documentElement->appendChild($article);
echo $doc->savexml();



function newArticle(DOMDocument $doc)
{
    $article=$doc->createElement("article");
    $article->setAttribute("id", 2);
    $published=$doc->CreateElement("published");
    $publishedDate=$doc->createTextNode(date("d/m/Y h:i:s", strtotime("tomorrow")));
    $published->appendChild($publishedDate);
    $article->appendChild($published);
    $author=$doc->createElement("author");
    $author->setAttribute("position", "writer");
    $authorName=$doc->createTextNode("Ivan Dimov");
    $author->appendChild($authorName);
    $article->appendChild($author);
    return $article;
}

function getData() {
return <<< eox
<?xml version="1.0" encoding="UTF-8"?>
<articles>
    <article id="1">
        <published>05/01/2015 04:32:36</published>
        <author position="writer">John Stewart</author>
    </article>
</articles>
eox;
}

prints

<?xml version="1.0" encoding="UTF-8"?>
<articles>
  <article id="1">
    <published>05/01/2015 04:32:36</published>
    <author position="writer">John Stewart</author>
  </article>
  <article id="2">
    <published>06/01/2015 12:00:00</published>
    <author position="writer">Ivan Dimov</author>
  </article>
</articles>
Sign up to request clarification or add additional context in comments.

4 Comments

It's still possible the OP wants to include the list of articles as a fragment/entity in a/another xml document - makes appending elements easier. In that case the article elements could be a "top-level" sequence. But then the xml declaration has to be removed.
Looks i didn't know few things about XML, cool to know @VolkerK, actually perfect example as well, but somehow i can't make it save just print. (i remove that "echo" before save) Can you find a bit more time to help me with let your perfect example work for me? Thanks p.s. Already have thumb up from me.
you have to revert to ->save() instead of ->savexml(). Same as with loadxml()/load(). .oO( wouldn't it be cool if load()/save() took a stream parameter instead of having separate loadxml()/savexml() methods? )
You should never have multiple top level element nodes in a document, that's what a document fragment is for.
1

You are getting a nested element, whereas you just need a new one in the same level of the first. So just use

$dom->appendChild($article);

instead of

$dom->documentElement->appendChild($article);

I tried it with your script and I get:

<?xml version="1.0" encoding="UTF-8"?>
<articles id="1"><published>05/01/2015 04:23:18</published><author position="writer">John Stewart</author></articles>
<articles id="2"><published>06/01/2015 12:00:00</published><author position="writer">Ivan Dimov</author></articles>

So the full code would be:

<?php

$dom=new DOMDocument();
$dom->load("articles.xml");

$article=$dom->createElement("articles");
...
$article->appendChild($author);
//$dom->documentElement->appendChild($article); // commented
$dom->appendChild($article);                    // the good one

$dom->save("articles.xml");

Info taken from DOMDocument::createElement in php.net in the first full example: Example #1 Creating a new element and inserting it as root

// Example #1 Creating a new element and inserting it as root
<?php

$dom = new DOMDocument('1.0', 'utf-8');
$element = $dom->createElement('test', 'This is the root element!');

// We insert the new element as root (child of the document)
$dom->appendChild($element);

echo $dom->saveXML();
?>

6 Comments

You are RIGHT! Thank you mate. Will mark this answer as correct as soon as I will be able ..
But now you have an XML document with more than one root/top-level element.
@VolkerK yep, not a very canonical XML but apparently it is what the OP wanted.
@Andurit ah now I see you had further questions you commented in the other answer. No, just proceed and accept the answer that helped you the most. Too bad I didn't see it before. In the future, try to keep asking in the main question, instead of in comments.
Right now i make it work, it looks like pastebin.com/duSTKKfY, not sure if it's 100% correct for a code one and security and things like that but looks it atelast works
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.