[PHP/XML/XSL] Alle XML data uit een XML-bestand wordt getoond

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Graviton

graviton

08/03/2009 02:25:00
Quote Anchor link
Ik heb een XML-bestand waarin data mbt een aantal productgroepen staat, zoals DVD's en games. Op dit XML-bestand pas ik XSL-templates toe door aan de server-side met behulp van PHP de standaard PHP XSL-processor toe te passen. Zie code:


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

   $xslDoc
= new DOMDocument();
   $xslDoc->load("XSLbestand.xsl");

   $xmlDoc = new DOMDocument();
   $xmlDoc->load("XMLbestand.xml");

   $proc = new XSLTProcessor();
   $proc->importStylesheet($xslDoc);
   echo $proc->transformToXML($xmlDoc);

?>


Nu werkt dit allemaal goed op 1 ding na. Alle data uit het XML bestand wordt nu getoond op het scherm.
Ik wil juist alleen bepaalde data op het scherm tonen welke zich tussen bepaalde XML-tags bevindt.
De bedoeling is bijvoorbeeld dat op een bepaalde pagina op de website alleen data mbt de DVD's wordt getoond, dus alleen producten welke tussen de <DVD> en </DVD> tags staan. Wat er nu gebeurt is dat alle data uit het XML bestand wordt getoond, ook alles dat tussen <GAMES> tags staat en dat is juist niet de bedoeling.

Ik weet dus alleen niet hoe ik dat moet doen met XSL (of PHP). (De XSL styling moet dus wel blijven werken op de gekozen data uit het XML-bestand.)

Iemand kwam met de volgende suggestie: "Onderdruk de XML elementen die je niet ge-output wil zien met een nieuwe lege XSL template".
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<xsl:template match="specifiekElement"></xsl:template>


Het bovenstaande lijkt me alleen handig in zeer specifieke gevallen, maar niet in mijn geval, want op de ene pagina wil ik een bepaald element wel tonen en op een andere pagina niet. Als ik een element permanent zou onderdrukken op de bovenstaande manier, dan heb ik die flexibiliteit namelijk niet om het XML element te tonen wanneer ik wil.

Een PHP oplossing zoals het volgende zou het ook kunnen laten werken, alleen is het volgende stukje code mijn eigen verzinsel en werkt het niet:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
//Echo alleen alles tussen de DVD-tags
echo $proc->transformToXML($xmlDoc->root[0]->dvd);

//Het bovenstaande stukje code geeft de volgende error:
//Warning: XSLTProcessor::transformToXml() expects parameter 1 to be object, null given

?>


Een andere oplossing is een X-Path expressie loslaten op het geladen XML bestand, echter de x-path functie werkt alleen op een SimpleXML object vermoed ik.
Gewijzigd op 01/01/1970 01:00:00 door Graviton
 
PHP hulp

PHP hulp

28/04/2024 16:03:33
 

08/03/2009 08:43:00
Quote Anchor link
Staat er niet hetzelfde op sitemasters en phpfreakz?
Edit: Laten we tweakers d'r ook maar bij doen.
Gewijzigd op 01/01/1970 01:00:00 door
 
Rens nvt

Rens nvt

08/03/2009 10:09:00
Quote Anchor link
@Karl: goed gezien! Echt knap. Maar misschien is het handiger om te proberen de vraag te beantwoorden. Daar schieten de topic starter en andere phphulp lezers meer mee op.

@graviton: misschien heb je hier iets aan? http://us2.php.net/domxpath

@karl hieronder: arrogant??? Hij stelt een vraag! Daarbij heeft ie ook op die andere forums nog geen antwoord gehad, dus waar doe je moeilijk over?
Gewijzigd op 01/01/1970 01:00:00 door Rens nvt
 

08/03/2009 10:23:00
Quote Anchor link
Rens schreef op 08.03.2009 10:09:
@Karl: goed gezien! Echt knap. Maar misschien is het handiger om te proberen de vraag te beantwoorden. Daar schieten de topic starter en andere phphulp lezers meer mee op.

Ik vind het arrogant.
 
Graviton

graviton

08/03/2009 20:15:00
Quote Anchor link
De reden dat het gehele XML bestand wordt ge-output door de XSLT processor is waarschijnlijk omdat $xmlDoc->load() het gehele XMLbestand.xml als parameter meekrijgt. Misschien is er een manier om een beperkt gedeelte van het XML-bestand als parameter mee te geven. Ik weet alleen niet hoe ik dat zou moeten doen.

PS: Het lukte me niet om een oplossing te vinden voor dit probleem terwijl de deadline steeds dichterbij komt, vandaar dat ik besloot om op andere forums het probleem ook te posten.
Als goedmakertje zal ik de oplossing ook op elk forum posten, dan heeft elk forum extra content, elk met een oplossing voor het probleem.
Gewijzigd op 01/01/1970 01:00:00 door graviton
 
Bo az

Bo az

08/03/2009 20:25:00
Quote Anchor link
graviton schreef op 08.03.2009 02:25:
Een andere oplossing is een X-Path expressie loslaten op het geladen XML bestand, echter de x-path functie werkt alleen op een SimpleXML object vermoed ik.


Je hebt ook DOMXPath: http://nl2.php.net/manual/en/class.domxpath.php

Dus dan krijg je iets in de trant van:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$xp
= new domxpath($dom);
$result = $xp->query("/root/dvd");
?>
 
Frank -

Frank -

08/03/2009 20:44:00
Quote Anchor link
De XSLT zou alleen die elementen moeten pakken die worden genoemd in de XSLT. Zonder jouw XML en XSLT te kennen, kunnen we alleen maar raden wat er fout gaat.

Voorbeeldje die goed werkt:
XML
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <test>bullshit</test> <!-- XSLT doet hier niks mee -->
    <loop>
        <value>alleen deze output</value>
    </loop>
</root>

XSLT:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" encoding="UTF-8"/>
    
    <xsl:template match="/">      
        <xsl:for-each select="root/loop">
            <p>output: <xsl:value-of select="value"/></p>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Resultaat:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<p>output: alleen deze output</p>

Het element <test> zie je nergens terugkomen in de output, wordt niet door de XSLT opgepakt. En zo hoort het ook.
Gewijzigd op 01/01/1970 01:00:00 door Frank -
 
Martijn Wieringa

Martijn Wieringa

08/03/2009 21:26:00
Quote Anchor link
Je XSLT zou moeten definieren welke data wel/niet wordt geoutput, en op welke manier.
 
Graviton

graviton

08/03/2009 21:45:00
Quote Anchor link
Ik ben aan de slag gegaan met de suggestie van Boaz. Ik denk dat ik er qua oplossing bijna ben. Ik krijg echter alleen nog 1 foutmelding.

Foutmelding: Warning: DOMDocument::importNode() expects parameter 1 to be DOMNode

De reden voor de foutmelding vermoed ik is dat de methode importNode alleen een DomNode als parameter accepteert, terwijl ik het juist een DOMNodeList als parameter meegeef. De reden daarvoor is dat de xpath->query() methode alleen een DOMNodeList als output geeft. De reden waarom ik het toch op deze manier probeerde is omdat ik geen methode kon vinden in de DOMDocument klasse welke een DOMNodeList kon importeren.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
        $xslDoc
= new DOMDocument();
        $xslDoc->load("XSLbestand.xsl");        
        
        $xmlDoc = new DOMDocument();
        $xmlDoc->load("XMLbestand.xml");        
        
        $xpath = new DOMXpath($xmlDoc);        
        $extractedElements = $xpath->query("/root/dvd");        
        
        $xmlDocStripped = new DOMDocument();
        $xmlDocStripped->importNode($extractedElements);                
        
        $proc = new XSLTProcessor();
        $proc->importStylesheet($xslDoc);
        
        echo $proc->transformToXML($xmlDocStripped);
?>
Gewijzigd op 01/01/1970 01:00:00 door graviton
 
Graviton

graviton

08/03/2009 21:52:00
Quote Anchor link
@pgFrank:
Je snapt het probleem, maar ik zou juist wel verwachten dat ook <test> ge-output wordt, immers ik geef het hele XMLbestand.xml als input aan de XSLTProcessor in de vorm van een DOMDocument object.
Alles wordt dus ge-output en alleen elementen welke een template aan zich gekoppeld hebben worden gestyled, de rest wordt dan gewoon als ongestylde text ge-output.


@Pholeron:
Hoe zou men dat dan moeten definieren in een .xsl bestand?

Gelieve Niet Bumpen::
Twee of meer keer achter elkaar in een topic posten heet bumpen. Bumpen is pas na 24 uur toegestaan en kan een reden zijn voor de admins en moderators om een topic te sluiten. Gebruik indien nodig de Afbeelding knop om je tekst aan te passen.

SanThe.
Gewijzigd op 01/01/1970 01:00:00 door graviton
 
Frank -

Frank -

08/03/2009 22:03:00
Quote Anchor link
graviton schreef op 08.03.2009 21:52:
@pgFrank:
Je snapt het probleem, maar ik zou juist wel verwachten dat ook <test> ge-output wordt, immers ik geef het hele XMLbestand.xml als input aan de XSLTProcessor in de vorm van een DOMDocument object.
Alles wordt dus ge-output en alleen elementen welke een template aan zich gekoppeld hebben worden gestyled, de rest wordt dan gewoon als unformatted text ge-output.
Nee, dat zou niet best zijn wanneer het zo zou werken. Dan kun je nooit met XSLT een andere XML aanmaken, je krijgt dan altijd de originele XML samen met de nieuwe XML. En daarmee maak je 80% van de XSLT-toepassingen onbruikbaar.

met XSLT pak je die elementen en attributen die je hebben wilt. De rest doet XSLT niks mee, daar mag XSLT niks mee doen omdat jij ze niet hebt benoemd in jouw XSLT. Je moet expliciet opgeven wat je nodig hebt, alleen dat deel krijg je retour. Wanneer je unformated text retour krijgt, doe je iets fout in je XSLT. Maar omdat we daar nog niks van hebben gezien, kunnen we er ook niks aan veranderen/verbeteren.
 
Graviton

graviton

08/03/2009 22:13:00
Quote Anchor link
pgFrank schreef op 08.03.2009 22:03:
graviton schreef op 08.03.2009 21:52:
@pgFrank:
Je snapt het probleem, maar ik zou juist wel verwachten dat ook <test> ge-output wordt, immers ik geef het hele XMLbestand.xml als input aan de XSLTProcessor in de vorm van een DOMDocument object.
Alles wordt dus ge-output en alleen elementen welke een template aan zich gekoppeld hebben worden gestyled, de rest wordt dan gewoon als unformatted text ge-output.
Nee, dat zou niet best zijn wanneer het zo zou werken. Dan kun je nooit met XSLT een andere XML aanmaken, je krijgt dan altijd de originele XML samen met de nieuwe XML. En daarmee maak je 80% van de XSLT-toepassingen onbruikbaar.

met XSLT pak je die elementen en attributen die je hebben wilt. De rest doet XSLT niks mee, daar mag XSLT niks mee doen omdat jij ze niet hebt benoemd in jouw XSLT. Je moet expliciet opgeven wat je nodig hebt, alleen dat deel krijg je retour. Wanneer je unformated text retour krijgt, doe je iets fout in je XSLT. Maar omdat we daar nog niks van hebben gezien, kunnen we er ook niks aan veranderen/verbeteren.


Maar dat zou dus betekenen dat ik voor mijn XMLbestand.xml vele XSL bestanden moet gaan aanmaken. Want ik gebruik het XMLbestand.xml voor vele pagina's op de website. Dat zou betekenen dat ik voor elke pagina een ander .xsl bestand moet aanmaken, immers alleen XML elementen waar een template aan zit gekoppeld zou dan worden ge-ouput.

Mijn plan was om 1 XML bestand en 1 XSL bestand te hebben voor de hele website.
Gewijzigd op 01/01/1970 01:00:00 door graviton
 
Frank -

Frank -

08/03/2009 22:16:00
Quote Anchor link
Quote:
Mijn plan was om 1 XML bestand en 1 XSL bestand te hebben voor de hele website.
Heel slecht plan, dat is niet te onderhouden en niet te debuggen.

1 XML zou nog wel kunnen, al vreeeet het geheugen, 1 XSLT is ondoenlijk. Alleen al om het feit dat je ongetwijfeld een hele berg templates en functies nodig zult gaan hebben, wanneer je dat in één bestand zet, wordt het één grote klerezooi. Begin daar niet aan, daar ga je halverwege heel erg veel spijt van krijgen.

Knip de boel op in logische onderdelen en zorg voor een hele goede structuur. Het is net programmeren... ;)
 
Graviton

graviton

08/03/2009 23:05:00
Quote Anchor link
pgFrank schreef op 08.03.2009 22:03:
met XSLT pak je die elementen en attributen die je hebben wilt. De rest doet XSLT niks mee, daar mag XSLT niks mee doen omdat jij ze niet hebt benoemd in jouw XSLT. Je moet expliciet opgeven wat je nodig hebt, alleen dat deel krijg je retour. Wanneer je unformated text retour krijgt, doe je iets fout in je XSLT. Maar omdat we daar nog niks van hebben gezien, kunnen we er ook niks aan veranderen/verbeteren.


Het probleem waar alles uit het XML bestand ge-output werd lijkt nu opgelost. Nu worden inderdaad alleen de xml-elementen ge-output welke een template aan zich gekoppeld hebben. Het vreemde is, is dat ik niets veranderd heb aan het xsl bestand, ik vermoed dat het een toevallige glitch is geweest van de PHP engine bij het toepassen de templates. Nu lijkt alles inderdaad zo te werken zoals je aangeeft.

Echter zit ik nu nog wel met hetzelfde probleem, want zowel alle DVD data wordt ge-output alswel alles Games data, want beide elementgrroepen hebben templates aan zich gekoppeld. Op webpagina X dient alleen de DVD data ge-ouput te worden en op webpagina Y alleen alle Games data.

Ik weet dat ik heb beste dan verschillende XSL bestanden kan aanmaken zoals je aangeeft, maar ik wil het toch op deze manier proberen met 1 XSL bestand, anders ben ik bang dat ik een massa aan verschillende XSL bestanden moet gaan aanmaken. Ik denk dat ik er bijna ben. Alleen die foutmelding vormt nog een probleem. (Geen idee overigens wat voor problemen zich er kunnen voordoen als die opgelost is)
Gewijzigd op 01/01/1970 01:00:00 door graviton
 
Graviton

graviton

09/03/2009 20:38:00
Quote Anchor link
Het is gelukt, ik heb een oplossing gevonden. Bij mijn bovenstaande poging bleek ik veel te moeilijk te doen. De oplossing was het doorgeven van een parameter mbv PHP naar het XSL bestand.

PHP:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$xslDoc
= new DOMDocument();
$xslDoc->load("XSLbestand.xsl");        
        
$xmlDoc = new DOMDocument();
$xmlDoc->load("XMLbestand.xml");                
        
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);        
        
//Hier pass ik een GET variabele uit de url naar het XSL bestand
$proc->setParameter(null, 'product', $_GET['product']);        
                
echo $proc->transformToXML($xmlDoc);
?>


Ook in het XSL bestand definieer ik een "product" parameter. Afhankelijk van de waarde van de parameter kies ik doormiddel van choose en when statements met xpath de juiste range aan elementen en pas op die range de templates toe.

XSL: (De formatting is wat messed up, maar het punt is duidelijk denk ik)
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<xsl:param name="product" />


<xsl:template match="/">
     <xsl:choose>
          <xsl:when test="$product = 'dvd'">
        <xsl:for-each select="/root/dvd">
            <xsl:apply-templates/>
        </xsl:for-each>
      </xsl:when>
      <xsl:when test="$product = 'games'">
        <xsl:for-each select="/root/games">
            <xsl:apply-templates/>
        </xsl:for-each>
      </xsl:when>            
     </xsl:choose>        
</xsl:template>

<xsl:template match="/dvdElement">
     <!-- Hier worden de dvd elementen gestyled -->
</xsl:template>

<xsl:template match="/gamesElement">
     <!-- Hier worden de games elementen gestyled -->
</xsl:template>
Gewijzigd op 01/01/1970 01:00:00 door graviton
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.