Search code examples
phpxmlsimplexml

Generate XML file using PHP


I need to generate a XML file using PHP having the following structure. This file is a structure of a quiz, where each question has five answers. Question and answer texts are enclosed in CDATA.

<?xml version="1.0" encoding="UTF-8"?>
<QuizMaster>
<header version="0.36" exportVersion="1" />
    <data>
        <quiz>
            <autostart>false</autostart>
            <forms activated="false" position="0" />
            <questions>
                <question answerType="single">
                    <questionText><![CDATA[What is the city?]]></questionText>
                    <correctMsg />
                    <incorrectMsg />
                    <answers>
                        <answer points="1" correct="true">
                            <answerText html="false"><![CDATA[Kolkata]]></answerText>
                        </answer>
                        <answer points="1" correct="false">
                            <answerText html="false"><![CDATA[Delhi]]></answerText>
                        </answer>
                        <answer points="1" correct="false">
                            <answerText html="false"><![CDATA[Mumbai]]></answerText>
                        </answer>
                        <answer points="1" correct="false">
                            <answerText html="false"><![CDATA[Chennai]]></answerText>
                        </answer>
                        <answer points="1" correct="false">
                            <answerText html="false"><![CDATA[Goa]]></answerText>
                        </answer>
                    </answers>
                </question>
            </questions>
        </quiz>
    </data>
</QuizMaster>

I've tried the following PHP code. It starts giving error from the second answer (// Answer 2) where attributes for the answer element is declared. The error is like Warning: SimpleXMLElement::addAttribute(): Attribute already exists in C:\wamp\www\quiz stack.php on line 46. I have already incorporated this kind coding in a few other places in this project but in all the cases, each question had only one answer.

<?php
class SimpleXMLExtended extends SimpleXMLElement
{
    public function addCData($cdata_text)
    {
        $node = dom_import_simplexml($this);
        $no = $node->ownerDocument;
        $node->appendChild($no->createCDATASection($cdata_text));
    }
}

$xmlFile = 'quiz_file.xml';
$xml = new SimpleXMLExtended('<QuizMaster/>');
// header
$xml->header = NULL;
$xml->header->addAttribute('version', '0.36');
$xml->header->addAttribute('exportVersion', '1');
$xml->data = NULL;
// quiz
$xml->data->quiz = NULL;
$xml->data->quiz->autostart = ('false');
// forms
$xml->data->quiz->forms = NULL;
$xml->data->quiz->forms->addAttribute('activated', 'false');
$xml->data->quiz->forms->addAttribute('position', '0');
// Question Start
$xml->data->quiz->questions = NULL;
// Question answer loop starts here
$xml->data->quiz->questions->question = NULL;
$xml->data->quiz->questions->question->addAttribute('answerType', 'single');
// Question text
$xml->data->quiz->questions->question->questionText = NULL;
$xml->data->quiz->questions->question->questionText->addCData('What is the     city?');
$xml->data->quiz->questions->question->correctMsg = NULL;
$xml->data->quiz->questions->question->incorrectMsg = NULL;
// Answers start
$xml->data->quiz->questions->question->answers = NULL;
// Answer 1
$xml->data->quiz->questions->question->answers->answer = NULL;
$xml->data->quiz->questions->question->answers->answer->addAttribute('points', '1');
$xml->data->quiz->questions->question->answers->answer->addAttribute('correct', 'true');
$xml->data->quiz->questions->question->answers->answer->answerText = NULL;
$xml->data->quiz->questions->question->answers->answer->answerText->addAttribute('html', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText->addCData('Kolkata');
// Answer 2
$xml->data->quiz->questions->question->answers->answer = NULL;
$xml->data->quiz->questions->question->answers->answer->addAttribute('points', '1');
$xml->data->quiz->questions->question->answers->answer->addAttribute('correct', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText = NULL;
$xml->data->quiz->questions->question->answers->answer->answerText->addAttribute('html', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText->addCData('Delhi');
// Answer 3
$xml->data->quiz->questions->question->answers->answer = NULL;
$xml->data->quiz->questions->question->answers->answer->addAttribute('points', '1');
$xml->data->quiz->questions->question->answers->answer->addAttribute('correct', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText = NULL;
$xml->data->quiz->questions->question->answers->answer->answerText->addAttribute('html', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText->addCData('Mumbai');
// Answer 4
$xml->data->quiz->questions->question->answers->answer = NULL;
$xml->data->quiz->questions->question->answers->answer->addAttribute('points', '1');
$xml->data->quiz->questions->question->answers->answer->addAttribute('correct', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText = NULL;
$xml->data->quiz->questions->question->answers->answer->answerText->addAttribute('html', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText->addCData('Chennai');
// Answer 5
$xml->data->quiz->questions->question->answers->answer = NULL;
$xml->data->quiz->questions->question->answers->answer->addAttribute('points', '1');
$xml->data->quiz->questions->question->answers->answer->addAttribute('correct', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText = NULL;
$xml->data->quiz->questions->question->answers->answer->answerText->addAttribute('html', 'false');
$xml->data->quiz->questions->question->answers->answer->answerText->addCData('Goa');
// Write Data
$xml->saveXML($xmlFile);
?>

If I comment out the offending two lines (where addAttribute is applied to answer element) from each answer except answer 1, then the file is generated but with only one answer that contains the text in Answer 5.

Can anyone suggest if there is any workaround for this problem without changing SimpleXMLElement object?


Solution

  • You are using a code that was ment to be used with a single answer node, you should be adding childs instead:

    $answer2 = $xml->data->quiz->questions->question->answers->addChild('answer');
    $answer2->addAttribute('points', '1');
    $answer2->addAttribute('correct', 'false');
    $answer2->answerText->addAttribute('html', 'false');
    $answer2->answerText->addCData('Delhi');
    
    $answer3 = $xml->data->quiz->questions->question->answers->addChild('answer');
    $answer3->addAttribute('points', '1');
    $answer3->addAttribute('correct', 'false');
    $answer3->answerText->addAttribute('html', 'false');
    $answer3->answerText->addCData('Mumbai');
    

    Use this approach for all your answers (event the first answer).

    And now, taking a deeper look, you may have to use the addChild method for your answerText node also:

    $answer3Text = $answer3->addChild('answerText');
    $answer3Text->addAttribute('html', 'false');
    $answer3Text->addCData('Mumbai');
    

    So, the code should look like this for all your answers:

    $answer3 = $xml->data->quiz->questions->question->answers->addChild('answer');
    $answer3->addAttribute('points', '1');
    $answer3->addAttribute('correct', 'false');
    $answer3Text = $answer3->addChild('answerText');
    $answer3Text->addAttribute('html', 'false');
    $answer3Text->addCData('Mumbai');