1

This is my XML file.

<body>
   <div>
     <p time="00:00:08"> </p>
     <p time="00:00:10"> </p>
     <p time="00:00:13"> </p>
   </div>
</body>

Now I want to add time = "00:00:12" to the XML file, but in increasing order. So, before adding this time, I will have to compare the time with other times and then add it at appropriate location.

Can anybody suggest me how to do this. A sample code would very helpful.

6
  • possible duplicate of A simple program to CRUD node and node values of xml file Commented Jun 27, 2011 at 10:50
  • 2
    you dont need to have a specific order in the XML file. Sorting it is the responsibility of code consuming the XML file. Commented Jun 27, 2011 at 10:50
  • actaully the xml file will be used by JW player for adding captions to the video. At each 'time' there will be a caption, which will be played by JW player. That is why I wanted to sort the XML file. Commented Jun 27, 2011 at 10:54
  • yeah, like I said, it's not your responsibility to presort this for JWPlayer. JWPlayer has to sort the p elements by time. If it doesnt do that, file a bug report with them. On a sidenote, if the captions are in an ordered sequence, why are they not in an OL element instead? Commented Jun 27, 2011 at 10:57
  • Also, according to the W3 specs for Timed Text Markup Language (TTML) 1.0, there is no attribute time for p elements. Commented Jun 27, 2011 at 11:11

1 Answer 1

2

As was suggested in Gordon's answer, I would load the XML file into SimpleXML, append the node and then sort it.

I've commented the code below to explain it step-by-step.

<?php

// Open the XML file
$xml = file_get_contents("captions.xml");
// SimpleXml is an "easy" API to manipulate XML
// A SimpleXmlElement is any element, in this case it will be the <body> 
// element as it is first in the file.
$timestamps = new SimpleXmlElement($xml);

// Add our new time entry to the <div> element inside <body>
$timestamps->div->addChild("p", null);
// Get the index of the last element (the one we just added)
$index = $timestamps->div->p->count()-1;
// Add a time attribute to the element we just added
$e = $timestamps->div->p[$index];
$e->addAttribute("time", "00:00:12");
// Replace it with the new one (with a time attribute)
$timestamps->div->p[$index] = $e;

// Sort the elements by time (I've used bubble sort here as it's in the top of my head)
// Make sure you're setting this here or in php.ini, otherwise we get lots of warnings :)
date_default_timezone_set("Europe/London");

/**
 * The trick here is that SimpleXmlElement returns references for nearly
 * everything. This means that if you say $c = $timestamps->div->p[0], changes
 * you make to $c are made to $timestamps->div->p[0]. It's the same as calling
 * $c =& $timestamps->div->p[0]. We use the keyword clone to avoid this.
 */ 
$dates = $timestamps->div->children();
$swapped = true;
while ($swapped) {
    $swapped = false;
    for ($i = 0; $i < $dates->count() - 1; $i++) {
        $curTime = clone $dates[$i]->attributes()->time;
        $nextTime = clone $dates[$i+1]->attributes()->time;

        // Swap if current is later than next
        if (strtotime($curTime) > strtotime($nextTime)) {
            $dates[$i]->attributes()->time = $nextTime;
            $dates[$i+1]->attributes()->time = $curTime;
            $swapped = true;
            break;
        }
    }
}

// Write back
echo $timestamps->asXml();
//$timestamps->asXml("captions.xml");
Sign up to request clarification or add additional context in comments.

6 Comments

i am unable to swap the elements.
i tried using list( $timestamps->div[$i], $timestamps->div[$i+1]) = array( $timestamps->div[$i+1], $timestamps->div[$i]). Still it does not work
Mm, I guessed that bit - will start up my VM and get back to you.
I fixed my example. With a broken bubble-sort and lots of parse errors should teach me not to code off the top of my head :) Make sure to read the block note about references (look them up in the PHP manual if you're not sure what they are) - it was tripping me up for a while (thankfully I found http://stackoverflow.com/questions/1190026).
Thanks Ross. The code works fine on my localhost, but when i try to run it on my VPS it everything works fine, except $dates[$i]->attributes()->time = $nextTime; $dates[$i+1]->attributes()->time = $curTime; They are overwritten by null (""). Can you tell me what might be the problem?
|

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.