Autor Zpráva
Marian.x86
Profil
ahoj, strávil jsem nad tímto půl dne bez výsledku, a tedy bych si rád nechal poradit. XML struktura :

<Details Level="1">
<Section SectionNumber="0">
<Field Name="name1" FieldName="{CMDB.name}"><FormattedValue>text jak na to 1</FormattedValue><Value>text jak na to 1 - dodatek</Value></Field>
<Field Name="name2" FieldName="{example}"><FormattedValue>user six</FormattedValue><Value>user six - dodatek</Value></Field>
<Field Name="description" FieldName="{desc}"><FormattedValue>text example five</FormattedValue><Value>text example five - dodatek</Value></Field>
</Section>
</Details>

<Details Level="1">
<Section SectionNumber="0">
<Field Name="name1" FieldName="{CMDB.name}"><FormattedValue>text jak na to 2</FormattedValue><Value>text jak na to 2 - dodatek</Value></Field>
<Field Name="name2" FieldName="{example}"><FormattedValue>user six</FormattedValue><Value>user six - dodatek 2</Value></Field>
<Field Name="description" FieldName="{desc}"><FormattedValue>text example six</FormattedValue><Value>text example six - dodatek</Value></Field>
</Section>
</Details>


xml soubor je veliky cca 500MB. a teď potřebuji načíst do proměnných údaje, které se nacházejí v :
field name=name1 - údaj v tagu <Value>
field name=name2 - údaj v tagu <Value>
field name=description - údaj v tagu <Value>

tedy FormattedValue mne nezajímá

můj kód je následující :


$file = 'import.xml';


$reader = new XMLReader();

$reader->open($file);
    

while($reader->read()) {
   if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Section")    //otevrit node Section
   {
     while($reader->read())
     {
       if ($reader->nodeType == XMLReader::ELEMENT && $reader->getAttribute("Name") == "name1")      //identifikovat node Field s attributem name = name1
       {
         while($reader->read())
         {
           if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Value") echo $reader->readString()."<BR>";           //získat obsah node Value
         }
       }
       if ($reader->nodeType == XMLReader::ELEMENT && $reader->getAttribute("Name") == "name2")          //identifikovat node Field s attributem name = name2
       {
         while($reader->read())
         {
           if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Value") echo $reader->readString()."<BR>";                //získat obsah node Value
         }
       }
       if ($reader->nodeType == XMLReader::ELEMENT && $reader->getAttribute("Name") == "description")              //identifikovat node Field s attributem name = description
       {
         while($reader->read())
         {
           if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Value") echo $reader->readString()."<BR>";          //získat obsah node Value
         }
       }
     }
   }
}
$reader->close();



bohužel stále my to vypisuje úplně veškeré informace, tedy i FormattedValue


určitě jsem na něco zapomněl, poradíte prosím?

díky
karel0
Profil *
možná (jsem) offtopic, ale nejde použít xml_parse_into_struct?
juriad
Profil
Marian.x86:
Na tom ukázaném kousku to funguje.

Ale máš tam jiný problém, más do sebe zanořené nekonečné (alespoň do konce xml) smyčky. Jakmile se skript dostate k první Section, bude zbytek souboru zpracováván jen tou smyčkou na 12. řádku. A tak dále - směrem dovnitř. Tedy jakmile skript najde první element Value, který má vytisknout, tak od té doby bude tisknout každý Value, ať je v xml kdekoli.
V tom skriptu není nic, co by umožňovalo tisknout něco jiného než obsah elementů Value (na to se můžeš spolehnout), ale nemůžeš se v současné implementaci spolehnout, který Value to bude.

Neexistuje totiž způsob, jak při konci Section vyskočit ven. Musel bys odchytávat uvnitř ještě END_ELEMENT, a pokud se bude jednat o element s názven Section, tak breaknout.

karel0:
Marian.x86 používá záměrně XMLReader, který je nenáročný na paměť, byť použít ho na něco složitějšího je fakt maso. Načíst půl giga do polí v PHP mu rozhodně nepomůže.
Marian.x86
Profil
AHoj juriad a diky moc za nakopnutí správným směrem. vyřešil to řádek navíc :-)

if ($xml->nodeType == XMLReader::END_ELEMENT && $xml->name == "Value") break;

(pod řádek 18)


před tím jsem úspěšně používal simplexml_load_file ale vstupní data narostly tak musím aktualizovat kód
juriad
Profil
Marian.x86:
Ten jeden řádek musíš vložit do každé smyčky.
Pokusím se za chvíli nastínit řešení, které je vhodnější.

Mimochodem, hledáš Value, který je přímým potomkem Field (s určitým jménem), který je přímým potomkem Section, které je někde zanořené v dokumentu?
Marian.x86
Profil
ahoj, ano vždy hledám obsah <Value> které je potomkem <Field Name="<example>"

s tím že v uvnitř <Section SectionNumber="0">je těch field name s atributem <example> asi dvacet

ted můj kod zrovna upravuji, bude funkční. Určitě existuje vhodnější řešení (třebas pomocí třídy) ale nemám čas si s tím pohrát a tak to napišu prasácky - if / while :-)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: