views:

50

answers:

1

I realize that my request is not possible using just SimpleXML -- that much I did figure out. Here is what I tried:

$newXML = simplexml_load_file($filePath); 
$domNewXML = dom_import_simplexml($newXML);
$domItem = dom_import_simplexml($items[$itemQty]);  <-- item I want to move
$domNewItem = $domItem->cloneNode(true);
$newNode = $domNewXML->importNode($domNewItem, true);
$domNewXML->getElementsByTagName('list')->item(0)->appendChild($newNode);

I realize the code errors out on line 5, because importNode is a function of the dom document, not the dom element, but how can I get the dom document to perform this step?

Am I going about this the right way?

In the grand scheme of things I have an XML file with at least 10 nodes, every day a CRON job checks to see if there are more than 10 nodes and if so, it's supposed to move the node from the current file into an archive file. I figured I would "move" the node by copying it to the archive file and deleting it from the original file.

Thanks for any help!

+1  A: 

You can get the owner document via $anyDOMNode->ownerDocument


Maybe it's not necessary to clone and insert the nodes into another document. If you split the archive into a) a skeleton xml document and b) an xml fragment that is included as an external entity into the document it suffices if you just append the xml string representation of the node to the end of the fragment file. E.g. as the skeleton

<?xml version="1.0"?>
<!DOCTYPE fooarchive [
  <!ENTITY entries SYSTEM "archive.fragment">
]>
<fooarchive>
  &entries;
</fooarchive>

and then the php script

$doc = new SimpleXMLElement('<a>
  <b>0</b><b>1</b><b>2</b><b>3</b>
  <b>4</b><b>5</b><b>6</b><b>7</b>
  <b>8</b><b>9</b><b>X</b><b>Y</b>
</a>');

$move = '';
for($i=10; $i<count($doc->b); $i++) {
  $move .= $doc->b[$i]->asXML();
}
file_put_contents('archive.fragment', $move, FILE_APPEND);

for($i=count($doc->b)-1; $i>9; $i--) {
  unset($doc->b[$i]);
}
echo $doc->asXML('current.xml');
VolkerK
I thought you could not unset nodes via simpleXML?What's the significance of the fragment?Your reply is very helpful by the way -- thank you!
Ryan S.
Is it so it will append after the right node?
Ryan S.
What gave you the impression that you can't unset nodes/elements via SimpleXML? The "interesting" thing about the fragment is that you don't have to parse it when appending an element. That's good for large documents and performance hungry applications. But _if_ you chose this technique try first whether and how your consumer application resolves the external entity (e.g. firefox doesn't).
VolkerK
That's very clever. Thank you VolkerK!
Ryan S.
OK, I've had some time to think this through. My archives are by month, so I'm guessing I can have one skeleton file and monthly archive files that contain respective entries. Using PHP, is there a way to supply an argument to a skeleton XML file to specify which fragment file to call? Thanks, Ryan.
Ryan S.
If you serve the skeleton via php, of course. Can be as simple as `<!ENTITY entries SYSTEM "archive.<?php echo date('Ym'); ?>.fragment">`
VolkerK
That is true and I should be able to do that. Maybe today is the day I finally finish this last component! Thanks again!
Ryan S.