Avatar billede thesaint Nybegynder
09. maj 2007 - 14:58 Der er 8 kommentarer

Parsing af XML der indeholder CDATA

Jeg har desværre ikke adgang til SimpleXML / PHP5 og har problemer med at lave et udtræk af XML så snart der optræder CDATA, eksempelvis a la:
<?xml version="1.0" encoding="utf-8" ?>
- <wine_info version="1.1">
- <wineid>
- <![CDATA[ Chateau Petrus]]>
  </wineid>
- <bio>
- <![CDATA[ Most known chateau in Pomerol]]>
  </bio>
- <price>
- <![CDATA[ Price ranges from USD 300 and up]]>
  </price>
.
.
.
</wine_info>

Er der nogle der har set et lille kodeeksempel der eksempelvis kan parse ovennævnte således at følgende resultat bliver echo'et i PHP:
Chateau Petrus
Most known chateau in Pomerol
Price ranges from USD 300 and up


etc.

På forhånd mange tak ;)
P.S. Skal til fodbold men logger på i aften
Avatar billede olebole Juniormester
09. maj 2007 - 15:13 #1
<ole>

Hvad gør du - og hvilke problemer har du med CDATA-noden? Husk: den er jo en (child)node som alle andre  ;o)

/mvh
</bole>
Avatar billede barklund Nybegynder
09. maj 2007 - 15:22 #2
Lad være med at regexp-parse dig til det eller noget i den stil - det kan lade sig gøre, men brug hellere en eksisterende parser som der også findes i php4 (create_xml_parser hed den vist).

--
Morten Barklund
Avatar billede thesaint Nybegynder
09. maj 2007 - 22:12 #3
<help>
Hej Ole
Jeg har det problem med min nuværende parser, at den ikke mere kan udtrække de data jeg gerne vil have.
Den har tidligere fungeret, men efter at xml-filen er blevet ændret ( noget som jeg ikke har med at gøre ), da ændrede jeg min kode, der ganske givet vil se klodset ud for langt de fleste her.
Det betyder for mig, at intet som helst virker og de gange hvor jeg får enkelte data udtrukket, får jeg som regel enten tomme værdier eller værdier hvor der foran står anført <![CDATA[
og til sidst ]]>

Disse "TAGS" har ikke tidligere eksisteret i de anvendte xml-dokumenter.

Min nu total ikke-funktionelle kode ser således ud:
<?
// ------------------------------------------------- SETUP ----------------------------------------------
$vinside = 'red';        // ---- Avaliable Values:  "red","white", "rose" vælg relevant side
$table_output = true;            // ---- Mulige Values:  "true","false" vis vinens navn i table eller single column.
$category = Pauillac;            // ---- Avaliable Values:  "Pauillac","Pomerol","Margaux" etc. - evt NULL


// ---- Sæt xml source og side-url ( vinside )
switch ( $vinside ) {
    case 'red' :
        $xml_source = 'http://www.xxx.xxx/red.xml';
        $site_url = 'http://www.xxx.xxx';
        break;

    case 'white' :
        $xml_source = 'http://www.xxx.xxx/white.xml';
        $site_url = 'http://www.xxx.xxx';
        break;

    case 'rose' :
    default :
        $xml_source = 'http://www.xxx.xxx/rose.xml';
        $site_url = 'http://www.xxx.xxx';

}


// ---- hvis der er data så forsøg at parse
if ( $xml_content = file_get_contents( $xml_source ) ) {
   
    $xml_parser = xml_parser_create();
    xml_parse_into_struct( $xml_parser, $xml_content, $value, $full_index);
    xml_parser_free( $xml_parser );


    $items = array();
    foreach ( $value as $current_value ) {
        if ( $current_value['level'] == 3 ) {
            $items[] = $current_value;
        }
    }
    reset( $items );
   
   
    $item_count = count( $items );
    $wines = array();
    for ( $i = 0; $i < $item_count; $i += 2 ) {
   
        $current_wine_name = each( $items );
        $current_category = each( $items );
        $wines[ strtolower( $current_category['value']['value'] ) ][] = $current_wine_name['value']['value'];
   
    }

    // ---- hvis der er en kategori-parameter, vises den del af arrayet
    if ( isset( $_GET['category'] ) && !empty( $_GET['category'] ) && isset( $wines[ strtolower( $_GET['category'] ) ] ) ) {
        $category = $_GET['category'];
    }

    if ( $category !== null ) {
        $category = strtolower( $category );
        $new_wines = $wines[ $category ];
        $wines = array();
        $wines[ $category ] = $new_new wines;
    }

    // ------- OUTPUT
    if ( $table_output ) {

        // ---- hvor mange vine /række
        if ( $wine_count = count_wines( $wines ) ) {
            $max_rows = ceil( $wine_count / 4 );
        } else {
            $max_rows = 0;
        }


        echo '<table width="100%" cellspacing="0" cellpadding="0" border="0">' . "\n";
        echo '    <tr>' . "\n";
        echo '        <td valign="top">' . "\n";

    }


    $current_wine_number = 0;
    foreach ( $wines as $current_category => $wines_in_category ) {
        sort( $wines_in_category );

        // ---- i "table_output" mode bruges ikke et kategori-navn
        if ( ! $table_output ) {
            // ---- Print Kategori-navn
            echo $current_category . ' (' . count( $wines_in_category ) . ')<br>' . "\n";
        }

        foreach ( $wines_in_category as $current_wines ) {

            if ( $table_output ) {

                // ---- Hvis antallet af vine er større end det tilladte brydes op
                if ( $current_wine_number > $max_rows ) {
                    $current_wine_number = 0;

                    echo '</td>' . "\n";
                    echo '<td valign="top">' . "\n";

                }

            }

            echo '<font size="1" face="Verdana, Arial, Helvetica, sans-serif" color="#000000" size="1"><a href="' . $site_url . '/wineid=' . $current_wine'" target=_blank><span class="wine_name">' . $current_wine . '</span></a>' . "\n";
            if ( $show_category_name ) {
                echo '&nbsp;<span class="wine_category">' . $current_category . '</span>';
            }
            echo '<br>';

            // ---- forøg antallet af vine
            $current_wine_number++;

        }

    }
   
   
    if ( $table_output ) {

        echo '        </td>' . "\n";
        echo '    </tr>' . "\n";
        echo '</table>' . "\n";

    }

} else {

    echo 'Fejl ved åbning af XML-fil';

}

/**
* Tæl alle vine i vin-array
*
* @param array $wines_array
* @return int
*/
function count_wines( $wines_array ) {

    $ret = 0;
    if ( is_array( $wines_array ) && count( $wines_array ) > 0 ) {

        foreach ( $wines_array as $current_category => $wines ) {
            $ret += count( $wines );
        }

    }

    return $ret;

}

?>

og jeg er efterhånden lidt lost.
Håbede nogle eventuelt vidste hvordan man nemmest kunne udtrække de viste data øverst her på siden.

</help>
Avatar billede thesaint Nybegynder
09. maj 2007 - 23:18 #4
Har fundet en parser der klarede problemet.
Ved ikke rigtig hvem af Jer jeg skal give point ;) men ellers må I smide et svar. Lukker spørgsmålet imorgen middag.
Avatar billede thesaint Nybegynder
10. maj 2007 - 00:05 #5
Ups. Det gjorde den så ikke alligevel.
Parseren er som følger:
<?php
$file = "XML_fil.xml";
$map_array = array(
    "BOLD"    => "B",
    "EMPHASIS" => "I",
    "LITERAL"  => "TT"
);

function startElement($parser, $name, $attrs)
{
    global $map_array;
    if (isset($map_array[$name])) {
        echo "<$map_array[$name]>";

    }
}

function endElement($parser, $name)
{
    global $map_array;
    if (isset($map_array[$name])) {
        echo "</$map_array[$name]>";
    }
}

function characterData($parser, $data)
{
    echo $data;
echo '<BR>';

}

$xml_parser = xml_parser_create();
// use case-folding so we are sure to find the tag in $map_array
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($file, "r"))) {
    die("could not open XML input");
}

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);
?>

men det jeg nu har problem med er, at de $data jeg får ud, er jeg nødt til at have en form for sortering af mit array. Forstået på den måde at jeg gerne vil kunne have en liste således at:
$liste[0]="Chateau Petrus" 
$liste[1]="Most known chateau in Pomerol"
$liste[2]="Price ranges from USD 300 and up"

etc.

Hjælp. ;)
Avatar billede barklund Nybegynder
10. maj 2007 - 10:33 #6
Du er nødt til at læse hele filen ind før du parser XML - du kan ikke nøjes med at læse 4096 bytes af gangen. Brug dog file_get_contents() :)

Derefter, hvorfor echo'er du alt muligt ud og hvad bruger du map_array til? Har du bare råt kopieret en anden funktion uden at vide, hvad den gør?

--
Morten Barklund
Avatar billede thesaint Nybegynder
10. maj 2007 - 11:16 #7
Hele filen bliver læst ind, da den aldrig vil andrage mere end de anførte 4096.
Jeg har echo'et $data for at kunne se, hvad der blev hentet, underforstået, at alt blev hentet.
$map_array har jeg ikke behov for. Problemet er som sagt nu, at jeg ikke ved hvordan jeg kan trække de respektive data ud i listeform.
Avatar billede barklund Nybegynder
10. maj 2007 - 11:45 #8
Så lad være med at have en while - hent filen rigtigt eller skriv hvorfor du mener du henter filen rigtigt - ovenstående er simpelthen noget bæ!

Og ovenstående scripts primære formål er at mappe nogle tags fra et navn til et andet og outputte det igen. Hvis du ikke skal det, så fjern alt det, du ikke skal bruge.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester