webForumDet fria alternativet

xml parsing.. eller nåt

6 svar · 418 visningar · startad av UrMe

UrMeMedlem sedan apr. 2001762 inlägg
#1

Det ligger till så här att jag har en .xml fil som jag hämtar ut information med hjälp av php.
XML filens uppbyggnad:

<keep name="Caer Renaris" realm="Albion">
  <owner>Albion</owner> 
  </keep>
<keep name="Caer Hurbury" realm="Albion">
  <owner>Albion</owner> 
  <claimant>Lusitania High Council</claimant> 
  <claimant_guildurl>No website entered</claimant_guildurl> 
  <claimant_heraldurl>tjoho.html</claimant_heraldurl> 
</keep>

Sedan kommer php koden här:

<?php
function startElement($parser, $name, $attrs=''){
    global $current_tag,$thename, $therealm;
    $current_tag = $name;
    switch($name){
        case 'KEEP':
		 $thename[]=$attrs['NAME'];
		 $therealm[]=$attrs['REALM'];
        break;
        default:
        break;
    }
}
function endElement($parser, $name, $attrs=''){
    global $current_tag;
    switch($name){
        case 'OWNER':
        case 'CLAIMANT':
        case 'CLAIMANT_URL':
        case 'CLAIMANT_HERALDURL':
        case 'KEEP':
        $current_tag = '';
        break;
        default:
        break;
    }
}

function characterData($parser, $data){
    global $current_tag, $theowner, $theclaimant, $theclaimanturl, $theclaimantheraldurl;
    switch($current_tag){
        case 'OWNER':
		 $theowner[]=$data;
		 break;
        case 'CLAIMANT':
		 $theclaimant[]=$data;
		 break;
        case 'CLAIMANT_URL':
		 $theclaimanturl[]=$data;
		 break;
        case 'CLAIMANT_HERALDURL':
		 $theclaimantheraldurl[]=$data;
		 break;
    default:
        break;
    }
}

$xml_file = xmlfil.xml';
$type = 'UTF-8';
$xml_parser = xml_parser_create($type);
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_set_element_handler($xml_parser, 'startElement','endElement');
xml_set_character_data_handler($xml_parser, 'characterData');

if (!($fp = fopen($xml_file, 'r'))) {
    die("Could not open $xml_file for parsing!\n");
}

$xmldata="";
while ($data = fread($fp, 4096)) {
    if (!($data = utf8_encode($data))) {
        echo 'ERROR'."\n";
    }
	$xmldata.=$data;
}
if (!xml_parse($xml_parser, $xmldata, true)) {
  die("XML error".xml_error_string(xml_get_error_code($xml_parser)));
}
xml_parser_free($xml_parser);

array_multisort ($therealm, SORT_STRING, $thename, $theowner, $theclaimant, $theclaimanturl, $theclaimantheraldurl);

echo '<table border="1">';
foreach ( $therealm as $key => $value ) {

if($key < 21)
{
	echo "<tr>";
	echo "<td>$therealm[$key]</td>";
	echo "<td>$thename[$key]</td>";
	echo "<td>$theowner[$key]</td>";
	echo "<td>$theclaimant[$key]</td>";
	echo "<td>$theclaimanturl[$key]</td>";
	echo "<td>$theclaimantheraldurl[$key]</td>";
	echo "</tr>\n";
}
}
echo'</table>';
?>

Problemet ligger nu i att om det inte finns nån t.ex "<claimant>" inuti "<keep>" i .xml filen så plockar den nästa "<claimant>" .. och det blir ju inte rätt..
För i detta fall skulle utskriften bli:

Caer Renaris | Albion | Albion | Lusitania High Council | No website entered | tjoho.html

Caer Hurbury | Albion | Albion

Nån som ser problemet? ..
För "Lusutania High Council tillhör ju <keep name="Caer Hurbury">

Åh.. jättesvårt att förklara :)

Fråga om nåt är oklart! ..

jarvkloMedlem sedan juli 20013 378 inlägg
#2

Hmmm...
Eftesom $arrayvariabel[]='värde' automatiskt skapar ett nytt indexvärde för just den arrayen just när tilldelningen görs - och inte annars, kommer du i obalans eftersom det medför att den array som inte tilldelas ett värde pga utebliven XML-tagg "hoppar över" ett index så att säga.
Exempel på vad jag menar:

a[]='foo'; b[]='foo' c[]='foo';
a[]='bar; c=[]bar;
a[]='baz'; b[]='baz' c[]='baz';

ger 'bar' 'baz' 'bar' när du plockar ut andra elementet ur respektive array.

Använd något lämplgt indexvärde och se till att den räknas upp i t.ex. startelement och sedan används vid alla tilldelningar.
i startElement:

global $mittindex;  
 ....  
$mittindex=$mittindex+1;
...
$thename[$mittindex]=$attrs['NAME'];

Efter den ändringen (och naturligtvis en inledande initiering av $mittindex=0 och användning av $mittindex i alla array-tilldelningar ;) ) kommer värden som inte anges att vara tomma i stället.

UrMeMedlem sedan apr. 2001762 inlägg
#3

Det fungerar bra ;) .. nu är det bara ett litet problem..
Om namnet är t.ex:
Olle's bil

Då delar han upp så att han lägger det så här:

$name[] = "Olle";
$name[] = "'";
$name[] = "s bil";

Alltså han bryter vid ' apostrofen... hur gör man för att inte bryta där? ...

För jag vill ju att det ska bli $name[] = "Olle's bil";

Tack på förhand!

jarvkloMedlem sedan juli 20013 378 inlägg
#4

*Ute på hal is* ;) - Funkar det om du använder addslashes() vid tilldelningen?

UrMeMedlem sedan apr. 2001762 inlägg
#5

Fast vart ska man lägga in addslashes()? .. om man gör det i funktionerna så blir är det ju redan "försent" .. för då har han redan delat upp strängen. Även fast det läggs ju till en \ före '

EDIT:
Hittade på php.net exakt det problemet jag har:
http://www.php.net/manual/en/function.xml-set-character-data-handler.php
Om ni läser inlägget av ken@positive-edge.com på den sidan.
Men jag blev inte klokare på det :)

jarvkloMedlem sedan juli 20013 378 inlägg
#6

Aha, är det *så* den gör!
Det innebär att det tack vare XML-parserns konstruktion inte går att använda "automatisk indexuppdatering vid tilldelning av arrayer" (dvs mittdata[]=$data) i t.ex. characterData(), utan att man måste använda både eget index (se ovan i denna tråd), och vara beredd på att slå ihop strängdatat man får med något som redan kan finnas...
Nånting i stil med

if isset(mittdata[$mittindex]) {
   mittdata[$mittindex].=$data; }
else {
   mittdata[$mittindex]=$data; }

krävs alltså...
Det var som f-n... :birp

UrMeMedlem sedan apr. 2001762 inlägg
#7

Guld ELOGE! Årets medlem :)
TACK!

124 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
121 ms — hämta tråd, inlägg och bilagor (db)