[PHP] XML Parser kapt alles voor speciale tekens af

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
Hoi,

ik werk met een php-xml parser om gegevens in een MYSQL database te krijgen. In de endElementHandler check ik op het voorkomen van een bepaalde node en dan voer ik een insert query uit. Nu is de xml-file ISO-8859-1 gecodeerd. Dus laat ik de parser de data "UTF-8" encoden en als ik de insert query uitvoer, decode ik het terug. Nu gaat dit allemaal goed, behalve als ik een vreemd karakter gebruik, zoals 'ë,à' of een enkele quote. Dan kapt ie alles voor het vreemde teken af. De htmlentities gebruiken doet ook niets. (Om even te tonen wat de output is, echo ik gewoon de gegevens in de endElementHandler)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="ISO-8859-1"?>
<Group>
 <Cat>
  <Number>1</Number>
  <LandNL>Nederland</LandNL>
</Cat>
<Cat>
  <Number>2</Number>
  <LandNL>België</LandNL>
</Cat>
<Cat>
  <Number>3</Number>
  <LandNL>Frank'rijk</LandNL>
</Cat>
</Group


zo wordt de parser geinitieerd

code:
1
2
3
4
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_SKIP_WHITE,TRUE); 
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,FALSE); 
xml_parser_set_option($xml_parser,XML_OPTION_TARGET_ENCODING,"UTF-8");


code:
1
2
3
4
5
function endElementHandler($parser, $name) {
global $values;
if ($name =="Cat") {
 echo utf8_decode($values["LandNL"])."<br />";
}


geeft als output:

Nederland
Belgi
ë
Frank
'rijk

Weet iemand wat hoe ik dit kan oplossen? thx

[ Voor 12% gewijzigd door Anoniem: 138552 op 04-07-2006 12:09 ]


Acties:
  • 0 Henk 'm!

  • _JGC_
  • Registratie: Juli 2000
  • Laatst online: 19:35
Je zou met <![CDATA[ rare tekens ]> tags kunnen werken. Een andere oplossing is het vervangen van je rare tekens door entities.

Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
_JGC_ schreef op maandag 03 juli 2006 @ 15:08:
Je zou met <![CDATA[ rare tekens ]> tags kunnen werken. Een andere oplossing is het vervangen van je rare tekens door entities.
Hey, de CDATA-sectie plaatsen voor elk woordje is onbegonnen werk... Maar de 2de optie is reeds gebeurd: Ik heb bijvoorbeeld ergens "de l'eau (de l'eau) staan ... en toch maakt hij er "eau" van....

Edit:
Ik dacht trouwens dat enkel
< less than
> greater than
& ampersand
' apostrophe
" quotation mark

geëscaped moeten worden in XML

[ Voor 28% gewijzigd door Anoniem: 138552 op 03-07-2006 15:53 ]


Acties:
  • 0 Henk 'm!

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
je output het als gewone html? en wat is daar de character encoding van?
als dat geen utf8 is (wat het standaard niet is), dan zou het daar nog wel eens aan kunnen liggen

Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
marty schreef op dinsdag 04 juli 2006 @ 01:05:
je output het als gewone html? en wat is daar de character encoding van?
als dat geen utf8 is (wat het standaard niet is), dan zou het daar nog wel eens aan kunnen liggen
Hey, normaal wordt het niet ge-output maar wordt het rechtstreeks met een query in de database gestoken...

Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Waarom eerst naar UTF-8 en vervolgens weer naar ISO-8859-1 coderen?
Is het niet mogelijk om XML_OPTION_TARGET_ENCODING op ISO-8859-1 in te stellen en utf8_decode niet te gebruiken?

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Anoniem: 138552 schreef op maandag 03 juli 2006 @ 15:25:
[...]

Edit:
Ik dacht trouwens dat enkel
< less than
> greater than
& ampersand
' apostrophe
" quotation mark

geëscaped moeten worden in XML
&apos; is zelfs in HTML en SGML geen geldige entity, maar de single quote hoef je doorgaans ook niet te encoden (het is encoding, geen escaping). Verder moeten alle tekens die niet in de gebruikte karakterset voorkomen geëncode worden. Belangrijk daarbij is dat je numerieke references gebruikt aangezien alleen de named entities van de 'special characters' gedefinieerd zijn in XML.
Wat is trouwens de karakterset van je database?

Intentionally left blank


Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
crisp schreef op dinsdag 04 juli 2006 @ 09:32:
[...]

&apos; is zelfs in HTML en SGML geen geldige entity, maar de single quote hoef je doorgaans ook niet te encoden (het is encoding, geen escaping). Verder moeten alle tekens die niet in de gebruikte karakterset voorkomen geëncode worden. Belangrijk daarbij is dat je numerieke references gebruikt aangezien alleen de named entities van de 'special characters' gedefinieerd zijn in XML.
Wat is trouwens de karakterset van je database?
Hoi, de karakterset is UTF-8 - collatie utf8_general_ci (stond eerst op latin1_swedish_ci). Wat bedoel je juist met numerieke references, kan je er een voorbeeld van geven. Thx

Edit: je zegt dat alle karakters ge-encode moeten worden. Maar dit gebeurd volgens mij toch al. De XML is iso-8859-1 (kan er zelf ook niet aan doen) - de parser heeft een target encoding van UTF-8 en voordat het in de database wordt geschreven wordt de data utf-8 gedecode...

Maar in principe krijg ik de vreemde tekens wel goed opgeslagen in de database... enkel het stuk wat ervoor moet staan ontbreekt dan..

[ Voor 27% gewijzigd door Anoniem: 138552 op 04-07-2006 10:31 ]


Acties:
  • 0 Henk 'm!

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
Hey, normaal wordt het niet ge-output maar wordt het rechtstreeks met een query in de database gestoken...
geeft als output:
:)

Ik bedoel dus: op het moment dat jij controleert wat er in de database staat, hoe doe je dat dan? Als je dat in een HTML pagina doet (waar je het misschien via een interface ook kan aanpassen) en die HTML pagina is niet UTF8, dan kan het dus best zo zijn dat het lijkt alsof het verkeerd in de database staat, terwijl de kink eigenlijk bij het weergeven op de pagina zit.

Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
marty schreef op dinsdag 04 juli 2006 @ 10:37:
[...]


[...]

:)

Ik bedoel dus: op het moment dat jij controleert wat er in de database staat, hoe doe je dat dan? Als je dat in een HTML pagina doet (waar je het misschien via een interface ook kan aanpassen) en die HTML pagina is niet UTF8, dan kan het dus best zo zijn dat het lijkt alsof het verkeerd in de database staat, terwijl de kink eigenlijk bij het weergeven op de pagina zit.
Hoi, de tekens staan goed in de database, enkel het stukje ervoor ontbreekt. Als er Natürlich moet staan, staat er ürlich (ik check het in phpMyAdmin, html dus)

[ Voor 4% gewijzigd door Anoniem: 138552 op 04-07-2006 10:53 ]


Acties:
  • 0 Henk 'm!

  • yiko
  • Registratie: September 2003
  • Laatst online: 20-04 20:19
Je voorbeeld is geen geldige xml :
code:
1
<LandNL>...</DefinitionNL>
Maar ik vermoed dat dit enkel in je voorbeeld zo is,en dus niet de oorzaak is van je probleem.

Om je xml te gaan verwerken heb je vermoedelijk een stuk code zoals dit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
$fp = fopen( $xml_filename ,"r" );

while ($data = fread($fp, 4096)) {
   if (!xml_parse($xml_parser, $data, feof($fp))) {
       die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($xml_parser)),
                   xml_get_current_line_number($xml_parser)));
   }
}
xml_parser_free($xml_parser);

fclose( $fp );


Telkens wordt er een stuk data ingelezen (hier 4096 bytes), en dit wordt gevoed aan de xml parser. Zo'n stuk data kan stoppen midden in de data van een tag, waardoor meerdere keren je "character_data_handler" wordt opgeroepen, en ik vermoedt dat hiermee geen rekening is gehouden.
Dit verklaart ook waarom je enkel het laatste stuk van je data overhoudt.

Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
yiko schreef op dinsdag 04 juli 2006 @ 11:06:
Je voorbeeld is geen geldige xml :
code:
1
<LandNL>...</DefinitionNL>
Maar ik vermoed dat dit enkel in je voorbeeld zo is,en dus niet de oorzaak is van je probleem.
Klopt, dit is enkel in het voorbeeld, ik heb het even aangepast.
Om je xml te gaan verwerken heb je vermoedelijk een stuk code zoals dit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
$fp = fopen( $xml_filename ,"r" );

while ($data = fread($fp, 4096)) {
   if (!xml_parse($xml_parser, $data, feof($fp))) {
       die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($xml_parser)),
                   xml_get_current_line_number($xml_parser)));
   }
}
xml_parser_free($xml_parser);

fclose( $fp );


Telkens wordt er een stuk data ingelezen (hier 4096 bytes), en dit wordt gevoed aan de xml parser. Zo'n stuk data kan stoppen midden in de data van een tag, waardoor meerdere keren je "character_data_handler" wordt opgeroepen, en ik vermoedt dat hiermee geen rekening is gehouden.
Dit verklaart ook waarom je enkel het laatste stuk van je data overhoudt.
Ik gebruik deze code inderdaad maar dat verklaart toch niet waarom de data altijd nèt afgekapt wordt bij een vreemd teken? Hoe zou ik er dan rekening mee kunnen houden in de character data handler?
Hier is mijn character data handler:
PHP:
1
2
3
4
5
function characterDataHandler($parser, $data) {
    global $currentTag, $values;
    $data = addslashes(trim($data));
    if (!empty($data)) $values[$currentTag] = $data;
}

[ Voor 23% gewijzigd door Anoniem: 138552 op 04-07-2006 12:28 ]


Acties:
  • 0 Henk 'm!

  • marty
  • Registratie: Augustus 2002
  • Laatst online: 27-03-2023
Anoniem: 138552 schreef op dinsdag 04 juli 2006 @ 10:41:
[...]


Hoi, de tekens staan goed in de database, enkel het stukje ervoor ontbreekt. Als er Natürlich moet staan, staat er ürlich (ik check het in phpMyAdmin, html dus)
En kijk eens wat er in de html-broncode van PHPMyAdmin staat voor de content meta-tag?
Als dit bijvoorbeeld:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
is, dan zit je dus met een andere character-endoding te kijken.

Ik blijf van mening dat daar je probleem zou kunnen zitten. Je bekijkt namelijk de data in je database volgens een iso-8859-15 character set, terwijl die in je database utf8 is. Dan is het niet gek dat sommige dingen verkeerd worden weergegeven

Acties:
  • 0 Henk 'm!

Anoniem: 138552

Topicstarter
marty schreef op dinsdag 04 juli 2006 @ 15:24:
[...]


En kijk eens wat er in de html-broncode van PHPMyAdmin staat voor de content meta-tag?
Als dit bijvoorbeeld:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
is, dan zit je dus met een andere character-endoding te kijken.

Ik blijf van mening dat daar je probleem zou kunnen zitten. Je bekijkt namelijk de data in je database volgens een iso-8859-15 character set, terwijl die in je database utf8 is. Dan is het niet gek dat sommige dingen verkeerd worden weergegeven
Dit is niet het probleem... ik ben ondertussen al iets verder en zie dat als er een vreemd karakter staat, 2x de character_data_handler wordt uitgevoerd... God knows why. Moet op één of andere manier dus gaan samenvoegen

[ Voor 3% gewijzigd door Anoniem: 138552 op 04-07-2006 15:54 ]


Acties:
  • 0 Henk 'm!

  • yiko
  • Registratie: September 2003
  • Laatst online: 20-04 20:19
Anoniem: 138552 schreef op dinsdag 04 juli 2006 @ 12:15:
Ik gebruik deze code inderdaad maar dat verklaart toch niet waarom de data altijd nèt afgekapt wordt bij een vreemd teken? Hoe zou ik er dan rekening mee kunnen houden in de character data handler?
Hier is mijn character data handler:
Dit is waarschijnlijk puur toeval dat dit net voor je speciale character is. Als je die tekens eens vervangt door iets anders, dan zal hoogst waarschijnlijk nog altijd op dezelfde plaatsen gestopt worden.

Hierin het kort hoe ik het ongeveer zou doen. Ik heb wel gewerkt met een class, omdat ik het gebruik van globale vars (je $currenttag en $values) maar vies vind. Het komt er dus op neer dat je in je characterdatahandler, controleer of je al data hebt voor die tag, en die daar in dat geval gewoon aan toevoegt, ipv te overschrijven.

PHP:
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
class Foo
{
    var $data       = array();
    var $currentTag = null;
    var $parser     = null;

    function Foo( $xmlfile )
    {
        $this->parser = xml_parser_create();
        xml_set_object( $this->parser , $this );
        xml_set_element_handler( $this->parser , "startElement" , "endElement" );
        xml_set_character_data_handler( $this->parser , "dataHandler" );

        // andere optie zetten van de xml parser + read loop
    }

    function startElement( $parser , $name )
    {
        $this->currentTag = $name;
        array_push( $this->data , null );
    }

    function endElement( $parser , $name )
    {
        $data = array_pop( $this->data );
        echo 'Data voor tag "' . $name . '" = "' . $data . '"' . PHP_EOL;
    }

    function characterData( $parser , $data )
    {
        $data = trim($data);
        if( ! empty( $data ) ) {
            $tmp = array_pop( $this->data );
            array_push( $this->data , $tmp . $data );
        }
    }
}

Is maar effen vlug uitgetypt, dus kunnen foutjes ingeslopen zijn. Hopelijk helpt dit.

[ Voor 6% gewijzigd door yiko op 04-07-2006 20:34 ]

Pagina: 1