[PHP4] Dynamische XML met XSL parsen

Pagina: 1
Acties:

  • Zoolander
  • Registratie: Januari 2003
  • Laatst online: 23-11-2022

Zoolander

superslim!

Topicstarter
Ik heb een PHP bestand dat een XML doc genereert vanuit mijn DB.
Dat gaat allemaal goed, dit is de code:

code:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php 
if (!$dbconnect = mysql_connect('localhost', '', '')) { 
   echo "Connection failed to the host 'localhost'."; 
   exit; 
} // if 
if (!mysql_select_db('test')) { 
   echo "Cannot connect to database 'test'"; 
   exit; 
} // if 

$table_id = 'xml'; 
$query = "SELECT * FROM $table_id"; 
$dbresult = mysql_query($query, $dbconnect);

// create a new XML document 
$doc = domxml_new_doc('1.0'); 

// create root node 
$root = $doc->create_element('zippers'); 
$root = $doc->append_child($root); 

// process each row from the sql query 
while ($row = mysql_fetch_assoc($dbresult)) { 

  // add node for each row 
  $occ = $doc->create_element($table_id); 
  $occ = $root->append_child($occ); 

  // add a child node for each field 
  foreach ($row as $fieldname => $fieldvalue) { 

  $child = $doc->create_element($fieldname); 
  $child = $occ->append_child($child); 

  $value = $doc->create_text_node($fieldvalue); 
  $value = $child->append_child($value); 

     } // foreach 
} // while 

// get completed xml document 
$xml_string = $doc->dump_mem(true); 

echo $xml_string; 
?>


en dit de output:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0"?>
<zippers>
  <xml>
    <zip>zip</zip>
    <zap>zap</zap>
    <nummer>1</nummer>
    <zop>zop</zop>
  </xml>
  <xml>
    <zip>zip1</zip>
    <zap>zap</zap>
    <nummer>0</nummer>
    <zop>zop</zop>
  </xml>
  <xml>
    <zip>zip2</zip>
    <zap>zap</zap>
    <nummer>0</nummer>
    <zop>zop</zop>
  </xml>
</zippers>


Nu wilke ik via een voorbeeld van PHP.net deze dynamische XML parsen met een statisch XSL(t) bestand.

Deze ziet er zo uit:

code:
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
26
27
28
29
30
31
<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/">
<html>
    <head>
        <title> XML Quiz </title>
        
    </head>

    <body>
                
        <xsl:apply-templates select="zippers/xml" />    
                
    </body>
</html>
    
    </xsl:template>

    
    <!-- Parse all available questions of the XML document -->
    <xsl:template match="xml">

    <div><xsl:value-of select="zip" /></div>
    <div><xsl:value-of select="zap" /></div><br />



    </xsl:template>

</xsl:stylesheet>


Maar het wil maar niet lukken.....
heb deze code om de transformatie te maken in PHP:

code:
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
<?php

// Gonna contain PHP-XML output
$arguments = array(
     '/_xml' => $xml,
);

$xh = xslt_create();

// Read plain PHP-XML output
$xmlData = fopen ("http://localhost/current/xslt/xml.php", "r");

// Stack up output into one String
while ($line = fgets ($xmlData))
  $xml .= $line;

// Process the document
$result = xslt_process($xh, 'arg:/_xml', 'http://localhost/current/xslt/test.xsl', NULL, $arguments); 

// Print out your transformed document
echo $result;

xslt_free($xh); 

?>


Krijg, wat ik ook doe de volgende error:

" Warning: Sablotron error on line 1: XML parser error 4: not well-formed (invalid token) in E:\Projects\Current\xslt\phpnetxml.php on line 20 "

Als ik de output btw in een XMLdoc zet, doet hij het wel!

Weet iemand wat ik fout doe?


PS. Is het handiger met zoveel bestanden dat ik ipv [code[ en [/code[ een URL gebruik waar jullie de bestanden vandaan kunnen plukken?
En wordt ik daarna niet op mijn domein doodgespammed door URLtrackers?

Thanx. _/-\o_

PS. Ik gebruik PHP 4.3.3 met Expat en Sablotron. Daarnaast staan de extensie php_xslt & php_dom geladen.

mijn naam slaat nergens op, althans niet op mij :P


  • Skaah
  • Registratie: Juni 2001
  • Niet online
PHP:
1
2
3
4
if (!$dbconnect = mysql_connect('localhost', '', '')) { 
   echo "Connection failed to the host 'localhost'."; 
   exit; 
}

Kun je herschrijven als:
PHP:
1
$dbconnect = mysql_connect('localhost', '', '') or die('connection failed to localhost');


En om even bij je probleem te komen,
PHP:
1
$xmlData = fopen ("http://localhost/current/xslt/xml.php", "r");

laad volgens mij de php data en niet de xml die je zoekt dankzij de url-wrappers.
Als ik het goed heb staat in het laatste code blok de var $xml, die alle xml data zou moeten bevatten. Dus, in plaats van met twee bestanden te werken (en een dikke filesystem overhead) zou je de $xml kunnen vullen vanuit het eerste bestand en daarna de relevante delen van het tweede bestand kunnen includen.

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Skaah schreef op 02 januari 2004 @ 17:37:
PHP:
1
2
3
4
if (!$dbconnect = mysql_connect('localhost', '', '')) { 
   echo "Connection failed to the host 'localhost'."; 
   exit; 
}

Kun je herschrijven als:
PHP:
1
$dbconnect = mysql_connect('localhost', '', '') or die('connection failed to localhost');
Maar vind je dit mooier?
En om even bij je probleem te komen,
PHP:
1
$xmlData = fopen ("http://localhost/current/xslt/xml.php", "r");

laad volgens mij de php data en niet de xml die je zoekt dankzij de url-wrappers.
Als ik het goed heb staat in het laatste code blok de var $xml, die alle xml data zou moeten bevatten. Dus, in plaats van met twee bestanden te werken (en een dikke filesystem overhead) zou je de $xml kunnen vullen vanuit het eerste bestand en daarna de relevante delen van het tweede bestand kunnen includen.
Dit lijkt me niet. Het is namelijk een webserver-adres, als jij met je browser naar http://localhost/bla.php gaat krijg je toch ook niet de source-code te zien.


ik zou je code 's hier in veranderen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Gonna contain PHP-XML output

$xh = xslt_create();

// Lees het xml bestand in
$xmlData = file_get_contents("http://localhost/meuk/xml/data.xml");
// Lees de style-sheet in
$xslt=file_get_contents("http://localhost/meuk/xml/style.xsl");

//Geef de arguments de goede waarde
$arguments = array(
     '/_xml' => $xml,
     '/_xslt' => $xslt
);

// Verwerk de zut
$result = xslt_process($xh, "arg:/_xml", "arg:/_xslt", NULL, $arguments); 

// En laat het maar zien!
echo $result;

xslt_free($xh);


Moet je alleen ff die directory's veranderen.

[ Voor 29% gewijzigd door chris op 02-01-2004 18:01 ]


  • Terranca
  • Registratie: April 2000
  • Laatst online: 11:02
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
// Gonna contain PHP-XML output
$arguments = array(
     '/_xml' => $xml,
);

...

// Read plain PHP-XML output
$xmlData = fopen ("http://localhost/current/xslt/xml.php", "r");

// Stack up output into one String
while ($line = fgets ($xmlData))
  $xml .= $line;


Denk inderdaad dat het aan dit deel ligt. Je geeft de $arguments["/_xml"] namelijk al de waarde $xml als hij al nog leeg is, aangezien het geen pointer is worden veranderingen die je later in $xml maakt niet doorgevoerd in $arguments. Ik zou dus $arguments pas z'n waarde geven als je alle xml data in $xml hebt gezet, dan zou het probleem toch wel verholpen moeten zijn.

PS: Sablotron is nog erg langzaam als je voor elke bezoeker moet parsen. Als de pagina dus erg vaak bezocht wordt kan je beter ook een server-side caching systeem inbouwen, meer informatie: [rml][ PHP/XSLT] Sablotron erg langzaam?[/rml]

[ Voor 26% gewijzigd door Terranca op 02-01-2004 18:41 ]


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Terranca: je hebt gelijk, maar: die error komt door het xslt gedeelte. Met mijn code moet het wel werken.

  • Terranca
  • Registratie: April 2000
  • Laatst online: 11:02
Ik krijg de exacte error ook als ik een fout in mijn XML maak, dwz als er opeens een php error tussen staat. Het kan dus best dat $xml gewoon leeg is, dan gaat hij dat proberen te parsen, wat niet lukt, en hij dan de error geeft dat de syntax van de xml niet goed is. Maar goed, jou oplossing zou inderdaad ook moeten werken, maar ik vind het een beetje onnodig om de xsl helemaal in te lezen terwijl het niet nodig is :) stukje efficentie :P

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Zoolander schreef op 02 januari 2004 @ 12:14:

PHP:
1
2
3
4
5
6
7
8
<?php
// Read plain PHP-XML output
$xmlData = fopen ("http://localhost/current/xslt/xml.php", "r");

// Stack up output into one String
while ($line = fgets ($xmlData))
  $xml .= $line;
?>
Goh, wat zou er hier nou gebeuren? Zou die de php code inlezen of ook echt uitvoeren :? Wat hier gebeurt is dat je alle php code gewoon inleest hoor... Je voert de php code gewoon aan de parser, geen wonder dat het niet well-formed is 8)7 ;)

[ Voor 5% gewijzigd door Michali op 03-01-2004 11:19 ]

Noushka's Magnificent Dream | Unity


  • Zoolander
  • Registratie: Januari 2003
  • Laatst online: 23-11-2022

Zoolander

superslim!

Topicstarter
Hmmm, oke Thanx!
Ik ga het even testen met jullie suggesties.

En.... ik gebruik liever ook geen Sablotron, maar hetzelfde in PHP5 met DOM lukte niet omdat ik gnome libxml2 in PHP5 B123 maar niet aan de praat krijg.....

Dus het is een beetje verplicht dat ik het in PHP4.3.3 doe met DOM/ SAX

Ik laat nog weten of het werkt!

mijn naam slaat nergens op, althans niet op mij :P


  • djluc
  • Registratie: Oktober 2002
  • Nu online
Nope Michaeli, een webserver stuurt gelukkig niet je source weg maar alleen de output tenzij je er natuurlijk een .phps van maakt.

[ Voor 4% gewijzigd door djluc op 03-01-2004 13:00 ]


  • Zoolander
  • Registratie: Januari 2003
  • Laatst online: 23-11-2022

Zoolander

superslim!

Topicstarter
Firebird, heb jou code getest. En die werkt idd, maar: je haalt de informatie uit op een statisch bestand. En ik wil het vanuit een DB omzetten in XML zonder de overhead van het schrijven naar een bestand.

Kan iemand dit trouwens met PHP5? Want dat zou ik SUPER SUPER SUPER vinden. (wil graag over op PHP5!)

BTW: is het normaal dat als je via deze methode de source opvraagt: deze er echt SLECHT en rommelig uitziet???
(dwz automatisch gegenereerd XML en statisch XSL)

[ Voor 21% gewijzigd door Zoolander op 03-01-2004 15:08 ]

mijn naam slaat nergens op, althans niet op mij :P


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Zoolander schreef op 03 januari 2004 @ 13:05:
Firebirdchris, heb jouw code getest. En die werkt idd, maar: je haalt de informatie uit op een statisch bestand. En ik wil het vanuit een DB omzetten in XML zonder de overhead van het schrijven naar een bestand.
Nou dan haal je toch die data uit het databeest, maakt er xml van en wijst het toe aan $xml? Wel redelijk basic imho.
Kan iemand dit trouwens met PHP5? Want dat zou ik SUPER SUPER SUPER vinden. (wil graag over op PHP5!)
Ja, dat kan maar php gebruikt geen sablotron meer. Een beetje een google-vraag
BTW: is het normaal dat als je via deze methode de source opvraagt: deze er echt SLECHT en rommelig uitziet???
(dwz automatisch gegenereerd XML en statisch XSL)
Hm, vreemd, is bij mij niet zo. Je bedoelt de output van je phpfile? Bij mij ziet het er standaard heel goed uit, met inspringen enzo. Nou, succes ermee. Je hebt nog een hoop te leren, zelf zoeken bijvoorbeeld :p ;)

  • Terranca
  • Registratie: April 2000
  • Laatst online: 11:02
Zoolander schreef op 03 januari 2004 @ 13:05:
BTW: is het normaal dat als je via deze methode de source opvraagt: deze er echt SLECHT en rommelig uitziet???
(dwz automatisch gegenereerd XML en statisch XSL)
Dat had ik eerst ook, even <xsl:output method="xhtml" indent="yes"/> ergens boven in de xsl file zetten en probleem was weg :) die method kan natuurlijk ook andere waardes aannemen.

  • Zoolander
  • Registratie: Januari 2003
  • Laatst online: 23-11-2022

Zoolander

superslim!

Topicstarter
Terranca schreef op 04 januari 2004 @ 00:39:
[...]


Dat had ik eerst ook, even <xsl:output method="xhtml" indent="yes"/> ergens boven in de xsl file zetten en probleem was weg :) die method kan natuurlijk ook andere waardes aannemen.
Kijk, daar heb ik wat aan!
Thanx, het ziet er nog niet helemaal super uit! Maar het meeste staat inderdaad netjes bij elkaar. Ga even zoeken welke outputs en properties je nog meer hebt!

En Chris (sorry van firebird) heb inderdaad nog veel te leren,
maar geloof me: PHP5 is NIET makkelijk uit te zoeken op google.
" Ja, dat kan maar php gebruikt geen sablotron meer. Een beetje een google-vraag " Dat weet ik ook, en ook dat het de gnome libxml2 gebruikt en level 2 DOM is. Maar krijg het niet aan de praat, that's all.

Maar omdat het bijna helemaal W3 is, wilde ik het wel graag gaan gebruiken. Omdat ik verwacht dat mijn eerste stable productie pas over 6 a 7 maanden klaar is.

[ Voor 24% gewijzigd door Zoolander op 04-01-2004 12:30 ]

mijn naam slaat nergens op, althans niet op mij :P


  • Nibbles
  • Registratie: Maart 2000
  • Laatst online: 16-04 12:46

Nibbles

just nibb it

Even een aanvulling voor de search, aangezien ik het nog nergens op GoT ben tegengekomen maar ik dit topic wel 25x ben tegengekomen op zoek naar een oplossing.

Het probleem dat hierboven wordt behandelt gaat over met PHP gegenereerde XML server side parsen door middel van bijvoorbeeld Sablotron. Het probleem was dus dat die fopen()'s ervoor zorgen dat je alleen de pure PHP code krijgt en geen netjes geparste XML. De work-around hiervoor was dus om via een http request het bestand op te vragen zodat de code netjes als XML geparsed is.

Met behulp van wat andere topics over content-types en dergelijke ben ik er toen wel uitgekomen. Er kwam echter een nieuw probleem naar voren zodra ik gebruik wilde gan maken van GET en POST vars. GET vars zou je kunnen meegeven bij de fopen() maar met POST vars gaat dat niet zo makkelijk.

Door echter gebruik te maken van een include() in plaats van een fopen() kun je de GET en POST variablen ook in het dynamische XML bestand gebruiken. Het enige probleem wat je dan nog tegen komt is dat de include zijn output direct geeft. Je wil echter de include output in een variable hebben zodat je hem aan Sablotron kan voeren. Met behulp van output buffering kan dit:

PHP:
1
2
3
4
5
6
ob_start();
// include dynamisch gegenereerde XML
include('xmlbestand.php');

$xmldata = ob_get_contents();
ob_end_clean();

Nu kun je dus $xmldata gebruiken in de xslt_process() en zo met de inhoud van de GET en POST variabelen rekening houden tijdens het creëren van de XML :)

Ik was naar een oplossing als deze op zoek omdat ik gebruikers de mogelijkheid wilde geven om te kiezen voor clientside of serverside XSLT transformatie. Op deze manier kan de GET- en POST-variabel verwerking in het XML bestand komen zodat je dus die mooie scheiding van inhoud en presentatie houdt. Ik heb er zelf nogal lang naar moeten zoeken dus ik hoop dat ik met deze post het een ander wat makkelijker maak. Ook als je geen gebruik maakt van de GET en POST variabelen denk ik dat dit een veel nettere manier is dan de fopen() via een HTTP request omdat er sprake is van minder overhead.

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Je gebruikt een beetje een kromme omweg volgens mij, maar je komt wel tot de juiste code. Ik gebruik ongeveer dezelfde manier om mijn gegenereerde XML via XSLT naar de user te sturen, en volgens mij is dit de netste manier.

Rustacean


  • Nibbles
  • Registratie: Maart 2000
  • Laatst online: 16-04 12:46

Nibbles

just nibb it

Zou je het duidelijk willen maken aan de hand van een voorbeeld of omschrijving? Het is een omweg zeg je, maar wat is dan wel de kortste manier? :)

[ Voor 53% gewijzigd door Nibbles op 25-03-2004 13:44 . Reden: Quote weggehaald ]


  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Je redeneert als volgt:

- Je wil dynamisch gegenereerde XML transformeren.
- Je kan de XML in PHP genereren en de output dan opvragen via HTTP.
- Als je dat doet is het doorgeven van evt. variabelen (GET en POST) lastig.
- Dus ga je het PHP-bestand includen in plaats van het opvragen van de output.
- Daarbij heb je de output-buffering van PHP nodig.

Mijn inziens was het logischer geweest als je zo had geredeneerd:

- Je wil dynamisch gegenereerde XML transformeren.
- Dus ga je output-buffering gebruiken om je XML op te vangen voor de transformatie.

Het resultaat is hetzelfde, maar je redering vind ik persoonlijk een beetje onlogisch: als dat niet hoeft is het altijd efficienter om geen HTTP-requests te doen.

Rustacean


  • Nibbles
  • Registratie: Maart 2000
  • Laatst online: 16-04 12:46

Nibbles

just nibb it

Daar heb je gelijk in.
De output buffering is alleen een oplossing die ik niet was tegengekomen toen ik de oplossing van de http request tegenkwam. Omdat ik toendertijd geen rekening heb gehouden met POST variabelen ben liep ik nu tegen een probleem. Om dit probleem op te lossen ben ik weer verder gaan zoeken waarna ik de oplossing van het output bufferen tegenkwam. Toen bedacht ik me dus gelijk dat ik deze oplossing al die tijd al beter had kunnen gebruiken, hetgeen ik ook in de laatste zin van mijn eerste post aangaf :)
Pagina: 1