[PHP] DomXML nodes verwijderen met XPath

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Mythix
  • Registratie: Oktober 2004
  • Laatst online: 18-09 13:41

Mythix

www.ctrl-f5.net

Topicstarter
Mijn bedoeling is volgens mij vrij duidelijk, een XML laden, nodes er uit trekken via XPath en deze verwijderen. Klinkt simpel maar is het blijkbaar niet.
Momenteel heb ik volgende code:
PHP:
1
2
3
4
5
6
7
8
9
$doc = new DOMDocument();
$doc->load($this->_xmlFile);
$xpath = new DOMXPath($doc);
$result = $xpath->query("//content/images/image[@id='{$id}']");

foreach ($result as $node){
    $node->unlink_node();
}
$doc->save($this->_xmlFile);

Het probleem is dat DOMXPath een lijst van DOMElement objecten returned, en enkel op DOMNode zit een functie unlink_node()...

met volgende code lukt het wel, maar zoals je wel kan afleiden is dit niet echt performant...
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$doc = domxml_open_file($this->_xmlFile,
            DOMXML_LOAD_PARSING + //0
            DOMXML_LOAD_COMPLETE_ATTRS + //8
            DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
            DOMXML_LOAD_DONT_KEEP_BLANKS //16
        );
$root = $doc->document_element();
$images = $root->child_nodes();
$image = $images[0]->child_nodes();

foreach ($image as $node){
    if ($node->get_attribute("id") == $id){
        $node->unlink_node();
    }
}
$doc->dump_file($this->_xmlFile);


Heb niet zoveel ervaring met XML en php, maar het zou mij verbazen als je enkel een bepaalde node kan verwijderen door heel het document te loopen.... 8)7

[ Voor 4% gewijzigd door Mythix op 20-02-2009 09:45 . Reden: DomXML->asXML() crashes apache... vervangen door DomXML->dump_file() ]

Whenever you find yourself on the side of the majority, it is time to pause and reflect


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

PHP:
1
 DOMElement    extends  DOMNode   {
:?

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Mythix
  • Registratie: Oktober 2004
  • Laatst online: 18-09 13:41

Mythix

www.ctrl-f5.net

Topicstarter
Mmmm en geen van beide blijkt een unlink_node te bevatten...
maar unlink_node() werkt wel heb het getest op PHP 5.2.6

Geen van beide classes bevat de unlink_node()
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DOMNode   {
    /* Methods */
    DOMNode appendChild ( DOMNode $newnode )
    DOMNode cloneNode ([ bool $deep ] )
    bool hasAttributes ( void )
    bool hasChildNodes ( void )
    DOMNode insertBefore ( DOMNode $newnode [, DOMNode $refnode ] )
    bool isDefaultNamespace ( string $namespaceURI )
    bool isSameNode ( DOMNode $node )
    bool isSupported ( string $feature , string $version )
    string lookupNamespaceURI ( string $prefix )
    string lookupPrefix ( string $namespaceURI )
    void normalize ( void )
    DOMNode removeChild ( DOMNode $oldnode )
    DOMNode replaceChild ( DOMNode $newnode , DOMNode $oldnode )
}
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
DOMElement extends DOMNode {
    /* Methods */
    __construct ( string $name [, string $value [, string $namespaceURI ]] )
    string getAttribute ( string $name )
    DOMAttr getAttributeNode ( string $name )
    DOMAttr getAttributeNodeNS ( string $namespaceURI , string $localName )
    string getAttributeNS ( string $namespaceURI , string $localName )
    DOMNodeList getElementsByTagName ( string $name )
    DOMNodeList getElementsByTagNameNS ( string $namespaceURI , string $localName )
    bool hasAttribute ( string $name )
    bool hasAttributeNS ( string $namespaceURI , string $localName )
    bool removeAttribute ( string $name )
    bool removeAttributeNode ( DOMAttr $oldnode )
    bool removeAttributeNS ( string $namespaceURI , string $localName )
    DOMAttr setAttribute ( string $name , string $value )
    DOMAttr setAttributeNode ( DOMAttr $attr )
    DOMAttr setAttributeNodeNS ( DOMAttr $attr )
    void setAttributeNS ( string $namespaceURI , string $qualifiedName , string $value )
    void setIdAttribute ( string $name , bool $isId )
    void setIdAttributeNode ( DOMAttr $attr , bool $isId )
    void setIdAttributeNS ( string $namespaceURI , string $localName , bool $isId )
    
    /* Inherited methods */
    DOMNode DOMNode::appendChild ( DOMNode $newnode )
    DOMNode DOMNode::cloneNode ([ bool $deep ] )
    bool DOMNode::hasAttributes ( void )
    bool DOMNode::hasChildNodes ( void )
    DOMNode DOMNode::insertBefore ( DOMNode $newnode [, DOMNode $refnode ] )
    bool DOMNode::isDefaultNamespace ( string $namespaceURI )
    bool DOMNode::isSameNode ( DOMNode $node )
    bool DOMNode::isSupported ( string $feature , string $version )
    string DOMNode::lookupNamespaceURI ( string $prefix )
    string DOMNode::lookupPrefix ( string $namespaceURI )
    void DOMNode::normalize ( void )
    DOMNode DOMNode::removeChild ( DOMNode $oldnode )
    DOMNode DOMNode::replaceChild ( DOMNode $newnode , DOMNode $oldnode )
}
DomNode->unlink_node

(No version information available, might be only in CVS)

DomNode->unlink_node — Deletes node

Description
void DomNode->unlink_node ( void )

Warning

This function is currently not documented; only its argument list is available.
Ik zal hier maar uit afleiden dat unlink_node nog niet in een productie versie zit en ik dit dus ook niet kan gebruiken.

momenteel heb ik het zo opgelost, zal het later wel eens bekijken hoe het beter kan via DOMNode->remove_child()
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//get the remaining elements
$doc = simplexml_load_file($this->_xmlFile);
$nodes = $doc->xpath("//content/images/image[@id!='$id']");

//generate XML
$innerXML = "";
foreach ($nodes as $node){
    $innerXML .= $node->asXML();
}

//create a new doc
$newDoc = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?><content><images>'.$innerXML.'</images></content>');
$newDoc->asXML($this->_xmlFile);


zoals je kan zien niet echt productiecode...

Whenever you find yourself on the side of the majority, it is time to pause and reflect


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Beetje laat, maar je kan altijd van een node de parentnode opvragen en daarmee de node verwijderen. Iets van: $node->parentNode->removeChild($node);

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz