Ich muss eine bestimmte entfernen Seg Element, mit einer ID von “A12”, wie kann ich das tun? Ich habe versucht, das durchzuschleifen Seg Elemente und ungesetztting das spezifische, aber das funktioniert nicht, die Elemente bleiben.
Entgegen der landläufigen Meinung in den vorhandenen Antworten kann jeder Simplexml-Elementknoten allein und aus dem Dokument entfernt werden unset(). Der springende Punkt ist nur, dass Sie verstehen müssen, wie SimpleXML tatsächlich funktioniert.
Suchen Sie zuerst das Element, das Sie entfernen möchten:
Entfernen Sie dann das in dargestellte Element $element Sie setzen seine Selbstreferenz:
unset($element[0]);
Das funktioniert, weil das erste Element jedes Elements das Element selbst in Simplexml ist (Selbstreferenz). Das hat mit seiner magischen Natur zu tun, numerische Indizes repräsentieren die Elemente in jeder Liste (zB Eltern->Kinder), und sogar das einzelne Kind ist eine solche Liste.
Nicht-numerische String-Indizes repräsentieren Attribute (beim Array-Zugriff) oder Kind-Element(e) (beim Eigenschaften-Zugriff).
Daher numerische Indizes im Eigenschaftszugriff wie:
unset($element->{0});
Arbeit auch.
Mit diesem xpath-Beispiel ist es natürlich ziemlich einfach (in PHP 5.4):
Diese Selbstreferenztechnik wurde früher (November 2010) demonstriert in: an answer to “PHP SimpleXML – XPath-Knoten entfernen”.
– hakre
21. Mai 2013 um 14:23 Uhr
Und diese simplexml-Selbstreferenztechnik wurde früher (Juni 2010) demonstriert in: an answer to “Wie kann ich den Textwert von SimpleXmlElement festlegen, ohne das übergeordnete Element zu verwenden?”
– hakre
22. Juni 2013 um 8:20 Uhr
Sehr gut erklärte Antwort. Ein Detail, das ich nicht sofort zu schätzen wusste, ist, dass Sie XPath nicht einfach aus der Schleife nehmen können, weil das Löschen eines Elements innerhalb eines Normals foreach ( $doc->seg as $seg ) Schleife verwirrt den Iterator (Faustregel: Ändern Sie die Länge eines Iterators nicht mitten in der Schleife). Die XPath-Implementierung von SimpleXML hat dieses Problem nicht, weil ihre Ergebnisse ein gewöhnliches Array nicht verwandter Elemente sind.
– IMSoP
12. September 2013 um 20:06 Uhr
@IMSoP: Für alle Traversable und dieses Problem (Live-Listen), kann ich sehr empfehlen iterator_to_arraysetzen in SimpleXML-Iteratoren den Schlüsselparameter auf FALSE, da SimpleXMLElement den Tag-Namen als Schlüssel verwendet, der in einer solchen Auflistung häufig doppelt vorhanden ist, und diese Funktion dann nur den letzten dieser gleichnamigen Knoten zurückgeben würde, wenn der zweite Parameter dies nicht ist FALSE.
– hakre
30. September 2013 um 9:00 Uhr
Guter Tipp, gerade was den Extra-Parameter angeht. 🙂
– IMSoP
30. September 2013 um 9:21 Uhr
Stefan Gehrig
Während SimpleXML bietet eine Möglichkeit, XML-Knoten zu entfernen, seine Änderungsmöglichkeiten sind etwas eingeschränkt. Eine andere Lösung besteht darin, auf die Verwendung von zurückzugreifen Dom Verlängerung. dom_import_simplexml() hilft Ihnen bei der Konvertierung SimpleXMLElement in ein DOMElement.
Übrigens: Die Auswahl bestimmter Knoten ist viel einfacher, wenn Sie XPath verwenden (SimpleXMLElement->xpath):
$segs=$doc->xpath('//seq[@id="A12"]');
if (count($segs)>=1) {
$seg=$segs[0];
}
// same deletion procedure as above
Vielen Dank dafür – anfangs war ich geneigt, diese Antwort zu vermeiden, da ich die Verwendung von DOM vermeiden wollte. Ich habe mehrere andere Antworten ausprobiert, die nicht funktionierten, bevor ich schließlich Ihre ausprobierte – die einwandfrei funktionierte. Für alle, die erwägen, diese Antwort zu vermeiden, probieren Sie sie zuerst aus und sehen Sie, ob sie nicht genau das tut, was Sie wollen. Ich denke, was mich abgeschreckt hat, war, dass ich nicht wusste, dass dom_import_simplexml() immer noch mit der gleichen zugrunde liegenden Struktur wie simplexml funktioniert, sodass alle Änderungen in einem sofort das andere beeinflussen, ohne dass geschrieben/gelesen oder neu geladen werden muss.
– dimo414
5. Juli 2010 um 2:01 Uhr
Beachten Sie, dass dieser Code nur das erste gefundene Element entfernt. Ich vermute, dass dies daran liegt, dass das Ändern der Daten während der Iteration die Position des Iterators ungültig macht, wodurch die foreach-Schleife beendet wird. Ich habe dies gelöst, indem ich die dom-importierten Knoten in einem Array gespeichert habe, das ich dann durchlaufen habe, um die Löschung durchzuführen. Keine tolle Lösung, aber es funktioniert.
– Ryan Ballantyne
12. September 2010 um 3:50 Uhr
Sie können SimpleXML-Elemente tatsächlich mit unset löschen. Eine Lösung finden Sie in der Antwort von posthy.
– Francois Feugeas
17. August 2011 um 16:05 Uhr
Eigentlich können Sie SimpleXML-Elemente mit unset löschen, aber es ist in meiner Antwort;) stackoverflow.com/a/16062633/367456
– hakre
17. April 2013 um 14:27 Uhr
Unset hat bei mir nicht funktioniert, aber die Dom-Methode hat sehr gut funktioniert. Dank dafür!
– Jarvis
20. Juli 2016 um 17:15 Uhr
datasn.io
Deaktivieren Sie einfach den Knoten:
$str = <<<STR
<a>
<b>
<c>
</c>
</b>
</a>
STR;
$xml = simplexml_load_string($str);
unset($xml –> a –> b –> c); // this would remove node c
echo $xml –> asXML(); // xml document string without node c
Dies funktioniert nur, wenn der Knotenname in der Menge eindeutig ist. Wenn dies nicht der Fall ist, entfernen Sie am Ende alle Knoten mit demselben Namen.
– Dallas
6. Dezember 2012 um 16:34 Uhr
@Dallas: Was Sie kommentieren, ist richtig, aber es enthält auch die Lösung. Wie greife ich nur auf das erste Element zu? Siehe hier: stackoverflow.com/a/16062633/367456
– hakre
17. April 2013 um 14:30 Uhr
Wittmann
Ich glaube, Stefans Antwort ist richtig. Wenn Sie nur einen Knoten entfernen möchten (und nicht alle übereinstimmenden Knoten), hier ein weiteres Beispiel:
//Load XML from file (or it could come from a POST, etc.)
$xml = simplexml_load_file('fileName.xml');
//Use XPath to find target node for removal
$target = $xml->xpath("//seg[@id=$uniqueIdToDelete]");
//If target does not exist (already deleted by someone/thing else), halt
if(!$target)
return; //Returns null
//Import simpleXml reference into Dom & do removal (removal occurs in simpleXML object)
$domRef = dom_import_simplexml($target[0]); //Select position 0 in XPath array
$domRef->parentNode->removeChild($domRef);
//Format XML to save indented tree rather than one line and save
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
$dom->save('fileName.xml');
Beachten Sie, dass die Abschnitte XML laden… (zuerst) und XML formatieren… (zuletzt) durch unterschiedlichen Code ersetzt werden können, je nachdem, woher Ihre XML-Daten stammen und was Sie mit der Ausgabe machen möchten; es sind die Abschnitte dazwischen, die einen Knoten finden und ihn entfernen.
Außerdem dient die if-Anweisung nur dazu, sicherzustellen, dass der Zielknoten existiert, bevor versucht wird, ihn zu verschieben. Sie können diesen Fall auf verschiedene Arten behandeln oder ignorieren.
+1 Dies ist erstaunlich perfekt für das, was es tut. Nein muss. Keine Aufregung.
– Giacomo1968
4. Oktober 2014 um 2:08 Uhr
Michal Tatarynowicz
Wenn Sie die Basisklasse SimpleXMLElement erweitern, können Sie diese Methode verwenden:
class MyXML extends SimpleXMLElement {
public function find($xpath) {
$tmp = $this->xpath($xpath);
return isset($tmp[0])? $tmp[0]: null;
}
public function remove() {
$dom = dom_import_simplexml($this);
return $dom->parentNode->removeChild($dom);
}
}
// Example: removing the <bar> element with id = 1
$foo = new MyXML('<foo><bar id="1"/><bar id="2"/></foo>');
$foo->find('//bar[@id="1"]')->remove();
print $foo->asXML(); // <foo><bar id="2"/></foo>
+1 Dies ist erstaunlich perfekt für das, was es tut. Nein muss. Keine Aufregung.
– Giacomo1968
4. Oktober 2014 um 2:08 Uhr
Josh Davis
Für die Zukunft: Das Löschen von Knoten mit SimpleXML kann manchmal mühsam sein, besonders wenn Sie die genaue Struktur des Dokuments nicht kennen. Deshalb habe ich geschrieben SimpleDOMeine Klasse, die SimpleXMLElement erweitert, um einige praktische Methoden hinzuzufügen.
Beispielsweise löscht deleteNodes() alle Knoten, die mit einem XPath-Ausdruck übereinstimmen. Und wenn Sie alle Knoten mit dem Attribut “id” gleich “A5” löschen möchten, müssen Sie nur noch Folgendes tun:
// don't forget to include SimpleDOM.php
include 'SimpleDOM.php';
// use simpledom_load_string() instead of simplexml_load_string()
$data = simpledom_load_string(
'<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>'
);
// and there the magic happens
$data->deleteNodes('//seg[@id="A5"]');
9895900cookie-checkEntfernen Sie ein untergeordnetes Element mit einem bestimmten Attribut in SimpleXML für PHPyes