Toon posts:

[PHP5/XML/XPATH] parents selecteren uit xml file

Pagina: 1
Acties:
  • 156 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Een vraagstuk waar ik niet helemaal uitkom... Ik heb hieronder een xml file geplaats waaruit ik mijn navigatie kan opbouwen. Daar gebruik ik XPath voor om nodes te selecteren en dat gaat prima.
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<context>
   <nodes>
      <node title="a" contentid="1"></nodes>
      <node title="b" contentid="2"></nodes>
      <node title="c" contentid="3"></nodes>
      <node title="d" contentid="4">
         <nodes>
            <node title="d1" contentid="6"></node>
            <node title="d2" contentid="7"></node>
            <node title="d3" contentid="8">
               <nodes>
                  <node title="d31" contentid="10"></node>
                  <node title="d32" contentid="11"></node>
                  <node title="d33" contentid="12"></node>
               </nodes>
            </node>
            <node title="d4" contentid="9"></node>
         </nodes>
      </nodes>
      <node title="e" contentid="5"></nodes>
   </nodes>
</context>

Nu wilde ik een extra functionaliteit aan mijn object toevoegen die met de XML file om kan gaan. Ik wilde een functie die netjes alle parent's tot de root teruggeeft als ik het contentid geef. Stel dat ik contentid 11 geef, dan wil ik uiteindelijk contentid 8 en 4 ook terug krijgen. Toen kwam ik uit op het gebruik van Axes wat er veel belovend uit zag, alleen kom ik er gewoon niet uit...

Het selecteren van //nodes/node[@contentid="11"] gaat prima, maar als ik parent::node[attribute::contentid="11"] probeer (en vele andere variante) probeer gaat dat niet goed en krijg ik helemaal niks terug. Wat doe ik helemaal fout of zie ik over het hoofd?

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Mischien omdat de node met contentid="11" geen child nodes heeft? Je specificeert nu eenmaal dat het een parent moet zijn en dat is het in dit geval niet. Of probeer je juist de parent node van die node te selecteren?

Noushka's Magnificent Dream | Unity


Verwijderd

Topicstarter
Ik probeer inderdaad de parent van node 11 te selecteren (en de parents die daarop volgen).

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Dan heb je sowieso de ancestor axis nodig. In dit geval zou nodes onder de node met contentid 8 geselecteerd moeten worden.

Noushka's Magnificent Dream | Unity


Verwijderd

Ik zou in dit geval geen ancestor axis gebruiken maar een geneste predicate:
code:
1
node[.//node[@contentid='11']]/@contentid

Oftewel alle nodes waarin een node zit met contentid='11'...en daar dan weer het attribuut contentid van :P

(niet getest)

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
He, ik wist niet dat dat kon :) Weer wat geleerd :P

Noushka's Magnificent Dream | Unity


Verwijderd

Topicstarter
Dat ziet er wel begrijpelijk uit! Hij doet ook wel wat, maar heb geen flauw idee wat ik er mee moet. Hij geeft een DOMNodeList Object terug als ik jou query draai. Ik kan verder ook weinig vinden over NodeList Object en wat ik er mee kan middels PHP. Onderstaand staat de methode die ik binnen mijn object gerbuik. Niets spannends dus...

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
function GetParentPath ($id)
{
    $xmlnode = $this -> DOMXPath -> query("node[.//node[@contentid='" . $id . "']]");
        
    print_r($xmlnode);  // geeft NodeList Object
    count($xmlnode);    // geeft 1
    
    foreach ($xmlnode as $node)
    {
        // hier komtie niet in
    }
}

Verwijderd

Volgens mij klopt m'n XPath toch niet en zou het:
//node[.//node[@contentid='11']]/@contentid
moeten zijn. Hij moet tenslotte alle nodes in de tree testen.

Meer info over de return values van query()

  • tech-no-logical
  • Registratie: December 2000
  • Laatst online: 24-04 14:10
het XPath

//*[@contentid='11']/ancestor::*

zou volgens mij alle ancestors (parents) moeten geven als nodelist. wil je de node zelf ook, dan :

//*[@contentid='11']/ancestor-or-self::*

garantie tot de deur, ik doe 't even uit m'n hoofd. voor axes en voorbeelden, zie

http://www.zvon.org/xxl/XSLTreference/Output/index.html

Verwijderd

Topicstarter
We zijn er bijna! De methode van Blues geeft mij direct netjes de nodes terug zonder de elementen nodes, hij neemt alleen zichzelf niet mee (element node met contentid 11 laat hij dus buiten beschouwing). de query van tech-no-logical doet dit wel, alleen krijg ik wel de elementen nodes mee. Deze twee ga ik vanavond proberen te combineren zodat ik de voorwaarde $node -> hasAttribute('key') niet meer nodig heb in de foreach lus. Hartstikke bedankt voor zover! Ben weer een hoop wijzer. Als ik er vanavond uitkom zal ik de aangepaste query plaatsen.

O ja, het attribute key staat niet in het xml voorbeeld in dit topic, maar in mn orginele file wel.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function GetParentPath ($id)
{
    // $xmlnode = $this -> DOMXPath -> query("//node[.//node[@contentid='" . $id . "']]");
    
    $xmlnode = $this -> DOMXPath -> query("//*[@contentid='" . $id . "']/ancestor-or-self::*");
    
    $parentpath = '';
            
    foreach ($xmlnode as $node)
    {
        if ($node -> hasAttribute('key'))
        {
            $parentpath .= '/' . $node -> getAttribute('key');
        }
    }
    
    return $parentpath;
}

  • tech-no-logical
  • Registratie: December 2000
  • Laatst online: 24-04 14:10
//*[@contentid='11']/ancestor-or-self::*[@key]

zou 't moeten doen. echter, als de node zelf dan geen attribute 'key' heeft, krijg je die niet (meer) terug...

Verwijderd

Topicstarter
Dat werkt idd goed! kom ik weer makkelijk van af! Ik kan in ieder geval garanderen dat een node een key heeft. Dus mag ik ervan uit gaan dat dat goed blijft gaan. Hartelijk dank voor de hulp en toelichting!
Pagina: 1