Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Mit XPath im DOMDocument PHP5 und der foreach Schleife einen Element WERT

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Mit XPath im DOMDocument PHP5 und der foreach Schleife einen Element WERT

    Guten Tag,

    ich schreibe Ihr zum ersten Mal, daher erst mal Hallo an Alle! Hoffe das meine Frage hier im richtigen Thread steht, sonst bitte verschieben. Ich stehe vor einem Problem und benötige dringend Ihre Hilfe, um in einem DOMDocument (PHP5) einem mittels XPath definiertem Ausdruck und (mit/über) zwei foreach Schleifen INDIREKT ermittelt werden soll.

    Indirekt deshalb, da ich erst den Richtigen Elternknoten ermitteln muss, (mit der If-Bedingung) um die Änderung auch Tatsächlich im richtigen Kindknoten vorzunehmen!

    Die XML Datei (log.xml):
    Code:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <users>
    <user id="23">
    <username>mustermann</username>
    <profile>0</profile>
    <userlocked>0</userlocked>
    <active>1</active>
    </user>
    <user id="24">
    <username>musterfrau</username>
    <profile>0</profile>
    <userlocked>0</userlocked>
    <active>1</active>
    </user>
    <user id="25">
    <username>mustermensch</username>
    <profile>0</profile>
    <userlocked>0</userlocked>
    <active>1</active>
    </user>
    </users>

    Mein Vorgehen:
    Ich zeige eben mein PHP5 Code, Kommentiert!
    PHP-Code:
    $edit 'profile'//zu ändernder Kindknoten
    $edit_content '1'//zu ändernder WERT
    $username 'mustermann'//Benutzer ermitteln

    $doc = new DOMDocument('1.0''iso-8859-1'); //Neues DOMDocument erstellen
    $doc DOMDocument::load("log.xml"); //XML Datei laden
    $doc->preserveWhiteSpace false;
    $doc->formatOutput true//richtig ausgeben

    //Anfang neuer Knoten
    $newtag $doc->createElement($edit); //neuen Knoten erstllen
    $newtag_content $doc->createTextNode($edit_content); //Textknoten anhängen
    $newtag->appendChild($newtag_content); //Textknoten zuweisen
    //ENDE neuer Knoten

    $xp = new domxpath($doc); //XPath definieren
    $titles $xp->query('//user'); //Xpath Ausdruck beschreiben
    foreach ($titles as $node)
    {
    foreach(
    $node->childNodes as $cnode//Kindknoten ermitteln
    {
    if(
    $cnode->nodeName == 'username' && $cnode->nodeValue == $username//wenn Username mit dem hinterlegten übereinstimmt
    {
    $cnode->parentNode->replaceChild($newtag$cnode); //HIER LIEGT DAS Problem, denn es wird nur das Kindelement Username ersetzt, das ist leider absolut FALSCH es muss das Geschwister ELEMENT "PROFILE" ersetzt werden
    echo 'ja der username stimmt überein und Ihr User Profil wurde aktiviert'//echo wird ausgegeben, doch eben leider falscher Kindknoten ersetzt
    }
    }
    }
    echo 
    $doc->save("log.xml"); //geänderte XML File abspeichern 

    Das Problem:
    Wie schon im Kommentar beschrieben wird leider nur das Kindelement "username" ersetzt, das ist eben absolut FALSCH es muss das Geschwister ELEMENT "PROFILE" ersetzt werden.

    Meine Frage:
    Wie kann ich "$cnode->parentNode->replaceChild($newtag, $cnode);" ändern, dass ich nun das GESCHWISTER ELEMENT => "PROFILE" ändere und NICHT das direkte KINDELEMENT vom parentNode?


    Ich bin um jede Hilfe dankbar und hoffe mich einigermaßen ausgedrückt zu haben! Beste Grüße


  • #2
    SInnvollerweise, indem Du den Knoten selbst auch suchst, den Du ersetzen willst. Klar kannst Du Dich mit XPath oder DOM-Traversing durchhangeln, was aber machst Du, wenn die XML Struktur mal anders ist oder geändert wird? Also: getElementsByTagName o.ä. benutzen und den Knoten ersetzen.

    Überhaupt hat Dein Code nicht viel mit DOM zu tun.
    PHP-Code:
    $xp = new domxpath($doc); //XPath definieren
    $titles $xp->query('//user'); //Xpath Ausdruck beschreiben
    foreach ($titles as $node)
    {
    foreach(
    $node->childNodes as $cnode//Kindknoten ermitteln
    {
    if(
    $cnode->nodeName == 'username' && $cnode->nodeValue == $username//wenn Username mit dem hinterlegten übereinstimmt
    {
    $cnode->parentNode->replaceChild($newtag$cnode); //HIER LIEGT DAS Problem, denn es wird nur das Kindelement Username ersetzt, das ist leider absolut FALSCH es muss das Geschwister ELEMENT "PROFILE" ersetzt werden
    echo 'ja der username stimmt überein und Ihr User Profil wurde aktiviert'//echo wird ausgegeben, doch eben leider falscher Kindknoten ersetzt
    }

    Bspw. kannst Du den Knoten direkt anspringen und Dir die ganzen Schleifen und Prüfungen sparen.

    PHP-Code:
    $users $xp->query('//user/username'); //Xpath Ausdruck beschreiben 
    [edit]
    Probier mal:

    PHP-Code:
    $users $xp->query('//user/[username="' .$username'"]/profile'); //Xpath Ausdruck beschreiben 
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --

    Kommentar


    • #3
      Danke @nikosch, für die schnelle Antwort!

      Hatte gleich den Vorschlag getestet, doch leider kommt dann folgende Fehlermeldung!
      Warning: DOMXPath::query() [domxpath.query]: Invalid expression in C:\xampp\htdocs\include\xmlreplace.php on line 21

      Wenn ich das so teste,
      PHP-Code:
      $users $xp->query('//user/[username="' .$username'"]/profile'); //Xpath Ausdruck beschreiben
      var_dump($users); 
      ergibt "var_dump()" folgendes:
      bool(false)

      Trotzdem nochmals danke für den Tipp.


      Versuch mit getElementsByTagName:

      PHP-Code:
      $i 0//Zählvariable
      $xp = new domxpath($doc); //XPath definieren
      $users $xp->query('//user/username');  //Xpath Ausdruck beschreiben
      foreach ($users as $node)
      {
               if(
      $node->nodeName == 'username' && $node->nodeValue == $username//wenn Username mit dem hinterlegten übereinstimmt
               
      {
               echo 
      $node->nodeValue '<br />'//Ausgabe des Element Wert von entsprechendem 'username'
               
      $profile $doc->getElementsByTagName('profile')->item($i)->nodeValue;  //Zum Usernamen den Passenden Element Wert von 'profile' ausgeben
               
      echo $profile '<br>';
               }
      $i++; //um eins hochzählen um stand bei '->item()' zu ermitteln

      Bisher kann ich schon den den dazugehörigen Wert ausgehend von <username> von <profile> ermitteln. Doch leider komm ich nicht drauf wie ich nun den Wert und das ermittelte Element ersetzen kann.

      Meine Frage:
      Wie ist es möglich das ich nun das eben ermittelte Element und dessen Wert ersetzen kann?


      Ich wäre sehr dankbar, wenn Sie mir dazu noch ein Ratschlag hätten. Beste Grüße!

      [edit]
      selbst gehilft und folgenden Code hinzugefügt:

      PHP-Code:
      $doc->getElementsByTagName('profile')->item($i)->nodeValue 'JA GUT OK HIER WIRD DER WERT GEÄNDERT'//Funktioniert super 
      Nochmal vielen Dank für den Super TIPP mit getElementsByTagName!

      Kommentar


      • #4
        Schade, lese das erst jetzt. Hatte ein Slash zuviel in der Syntax. Diese Form der XPath-Angabe ist mir nicht sehr geläufig. So gehts:

        //user[username="{value}"]/profile'

        wertet user nach einem darinliegenden node username mit dem Textinhalt {value} aus und sucht profile im zugehörigen user-Knoten. Sehr mächtiges Konstrukt. Gefunden hier: XPath Syntax
        PHP-Code:
        <?php

        $xml 
        ='<?xml version="1.0" encoding="ISO-8859-1"?>
        <users>
          <user id="23">
            <username>mustermann</username>
            <profile>14</profile>
            <userlocked>0</userlocked>
            <active>1</active>
          </user>
          <user id="24">
            <username>musterfrau</username>
            <profile>0</profile>
            <userlocked>0</userlocked>
            <active>1</active>
          </user>
          <user id="25">
            <username>mustermensch</username>
            <profile>0</profile>
            <userlocked>0</userlocked>
            <active>1</active>
          </user>
        </users>'
        ;


        $doc = new DOMDocument('1.0''iso-8859-1'); //Neues DOMDocument erstellen
        $doc->loadXML ($xml);

        $username 'mustermann';

        $xp = new domxpath($doc); //XPath definieren
        $users $xp->query('//user[username="' .$username'"]/profile'); //Xpath Ausdruck beschreiben  

        foreach ($users as $node) {
          echo 
        $node->nodeValue;  // 14
        }
        --

        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
        Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


        --

        Kommentar

        Lädt...
        X