XML Knoten umbenennen

Sixty

Mitglied
Hi,

ich möchte einen XML-Knoten z.B. "<haus>hochhaus</haus>" in "<mehrfamilienhaus>hochhaus</mehrfamilienhaus>" umbenennen.
Wie mache ich das mit PHP?
Also Knoteninhalte zu ändern ist mit SimpleXML kein Problem, nur der Knotenname macht mir zu schaffen.

Hat jemand eine Idee?
 
Servus,

du musst dir im Prinzip als Erstes den Knoteninhalt per SimpleXML holen und dann den "Knoten" aus dem XML-Objekt entfernen.
Danach legst du einen neuen Knoten an und speicherst dort den Wert des Ursprünglichen Knotens.
PHP:
$xmlstring = <<<EOT
<imobilie>
 <haus>hochhaus</haus>
</imobilie>
EOT;
$xml = new SimpleXMLElement($xmlstring); // dein XML evtl. auch per simplexml_load_file oder simplexml_load_string
$storage = (string)$xml->haus[0];
unset($xml->haus[0]);
$xml->addChild('mehrfamilienhaus', $storage);
$xml->asXML;

mfg
 
Zuletzt bearbeitet:
Dann würde ich das anders lösen und nicht mit SimpleXML.

Kleiner Vorschlag mit regulären Ausdrücken:
PHP:
$xmlstring = "..."; // dein XML in Textform (zb. aus einer Datei ausgelesen)
$patterns = array("/<(haus)>([^<]*)<\/\\1>/i", "/<(element)>([^<]*)<\/\\1>/i");
$replace = array("<mehrfamilienhaus>$2</mehrfamilienhaus>", "<neuerelementname>$2</neuerelementname>");
$newxmlstring = preg_replace($patterns, $replace, $xmlstring);
echo $newxmlstring;

mfg
 
Zuletzt bearbeitet:
Danke nochmals.

Das ist nicht so schön. Ich möchte lediglich eine Codezeile zum umbenennen haben, wie z.B. beim austauschen von Knoteninhalten mit SimpleXML:

$xml->haus = 'Hütte';


Hat sich vielleicht jemand schonmal mit DOMDocument::renameNode beschäftigt?
 
DOMDocument::renameNode() ist keine PHP-Funktion, hab mir grad nochmal deinen Link zum W3CSchools angeschaut. Dabei handelt es sich allerdings um Javascript Code.

Mit PHP geht "nur" replaceChild(). PHP-Doku: http://de.php.net/manual/de/domnode.replacechild.php

Bei dem Beispiel von vorhin muss du "nur" die Werte in den Arrays ändern, um alle zu ersetzenden Elemente zu ändern.
Wenn du das lediglich über SimpleXML lösen willst, musst du dort eine Schleife bauen und dort die Ersetzung durchführen.
 
Moin,
DOMDocument::renameNode
(no version information, might be only in CVS)
scheint mir so, als wäre das noch keine offizielle PHP-Funktion, da ich das auf php.net nicht finden kann. Bei der von dir geposteten Seite
steht auch keine Angabe, ab welcher PHP-Version das verfügbar ist. Es wird wohl erst in Zukunft verfügbar sein und ist damit für dich nicht einsetzbar.

Zu Erklärung des Codes vom mir mit den regulären Ausdrücken.

Die Funktion preg_replace (siehe: http://de.php.net/manual/de/function.preg-replace.php) sucht und ersetzt Zeichenketten in einem String.
Sowohl der zu suchende als auch der zu ersetzende Teil, kann als String oder Array definiert werden.
Will man nur einen einzigen String ersetzen, nutzt man als Such- und Ersetzungsmuster einen String. Sollen gelich mehrere Sachen ersetzt werden,
bietet sich die von mir verwendete Array-Variante an.

PHP:
$patterns = array("/<(haus)>([^<]*)<\/\\1>/i", "/<(element)>([^<]*)<\/\\1>/i");
$replace = array("<mehrfamilienhaus>$2</mehrfamilienhaus>", "<neuerelementname>$2</neuerelementname>");
$patterns ist das Array mit den Suchmustern
$replace ist das Array mit den Ersetzungsmustern

Enthalten sowohl das Such- als auch das Ersetzungsarray die gleiche Anzahl an Elementen, werden die Treffer der Reihe nach ersetzt, also Suchmuster1 mit Ersetzungsmuster1,
Suchmuster2 mit Ersetzungsmuster2 usw.

Nehmen wir uns mal ein Beispiel als gegebenes XML in $xmlstring:
HTML:
<immobilien>
 <datum>08.07.2010</datum>
 <haeuser>
  <villa>Villa 1</villa>
  <villa>Villa 2</villa>
  <villa>Villa 3</villa>
  <haus>Haus 1</haus>
  <haus>Haus 2</haus>
  <haus>Haus 3</haus>
  <haus>Haus 4</haus>
  <haus>Haus 5</haus>
 </haeuser>
 <garagen>
  <garage>Garage 1</garage>
  <garage>Garage 2</garage>
  <garage>Garage 3</garage>
 </garagen>
</immobilien>

Jetzt nehmen wir uns die Such- und Ersetzungsarrays und definieren die Werte:
PHP:
$patterns = array("/<(haus)>([^<]*)<\/\\1>/i", "/<(garage)>([^<]*)<\/\\1>/i", "/<(datum)>([^<]*)<\/\\1>/i");
$replace = array("<mehrfamilienhaus>$2</mehrfamilienhaus>", "<carport>$2</carport>", "<letzte_aenderung>$2</letzte_aenderung>");

Eine kurze Erläuterung zu einem einzelnen Suchmuster:
Code:
/<(haus)>([^<]*)<\/\\1>/i
findet alle Elemente mit den Namen haus und dem Text der dazwischen steht. Die \\1 sorgt dafür, dass der erste Klammerausdruck (haus) genommen wird.
Ausgeschrieben wäre auch folgende variante möglich:
Code:
<haus>([^<]*)</haus>

Der zweite Klammerwert findet den Text zwischen den Elementen. ([^<]*) sorgt dafür, das jedes Zeichen ausser dem < gefunden wird, sprich er geht bei der Suche
bis zum Anfang des schliessenden XML-Tags und hört mit der Suche auf.
Das $2 wird beim Ersetzen mit dem Wert des zweiten Klammenpaares ersetzt, also das, was die Suche mit ([^<]*) findet.

Übergeben die Arrays an die Funktion:
PHP:
$newxmlstring = preg_replace($patterns, $replace, $xmlstring);

Das würde folgendes Ergebnis bringen:
HTML:
<immobilien>
 <letzte_aenderung>08.07.2010</letzte_aenderung>
 <haeuser>
  <villa>Villa 1</villa>
  <villa>Villa 2</villa>
  <villa>Villa 3</villa>
  <mehrfamilienhaus>Haus 1</mehrfamilienhaus>
  <mehrfamilienhaus>Haus 2</mehrfamilienhaus>
  <mehrfamilienhaus>Haus 3</mehrfamilienhaus>
  <mehrfamilienhaus>Haus 4</mehrfamilienhaus>
  <mehrfamilienhaus>Haus 5</mehrfamilienhaus>
 </haeuser>
 <garagen>
  <carport>Garage 1</carport>
  <carport>Garage 2</carport>
  <carport>Garage 3</carport>
 </garagen>
</immobilien>

Für mehr Informationen über reguläre Ausdrücke kannst du hier: http://regexp-evaluator.de/tutorial/ nachschauen.

mfg
 
Zurück