2014-01-19 2 views
0

У меня есть вложенный XML-код, который мне нужно пройти и получить не только узлы, но и ключ и значение атрибута, каждый из которых отличается друг от друга.PHP анализирует следующий XML с уникальными атрибутами

Я попытался написать рекурсивную функцию в PHP, чтобы получить то, что искал. Мой XML выглядит следующим образом:

<document> 
<character> 
    <literal>name</literal> 
    <codepoint> 
     <cp_value cp_type="ucs">4e9c</cp_value> 
     <cp_value cp_type="jis208">16-01</cp_value> 
    </codepoint> 
    <radical> 
     <rad_value rad_type="classical">7</rad_value> 
     <rad_value rad_type="nelson_c">1</rad_value> 
    </radical> 
      <meaning_group> 
       <meaning>this</meaning> 
       <meaning>that</meaning> 
      </meaning_group> 
    </character> 
    ... 
</document> 

Проблема в том, что не все узлы [character] имеют одинаковые дети.

Я пытаюсь вытащить ключ и значение атрибута, чтобы объединить его в один ключ, а затем сопоставить значение как значение. Если атрибута нет, я хочу использовать имя тега в качестве ключа. Кроме того, некоторые дети имеют одинаковое имя без атрибута. В этом случае я хочу просто поместить их в одно поле, разделенное разрывом строки. Благодаря!!

["literal"] => "name", 
["cp_type-ucs"] => "4e9c", 
["cp_type-jis208"] => "16-01", 
["rad_type-classical"] => "7", 
["rad_type-nelson_c"] => "1", 
["meaning"] => "this\nthat" 

Это массив, который я хочу, чтобы вывести ...

Любые и вся помощь будет принята с благодарностью! Благодаря!

EDIT: Добавлен код, который я могу использовать для перемещения по уровням и получить имена тегов для эха, но по какой-то причине они не будут заполнять массив. Только тег «character» будет находиться в массиве.

function ripXML($file) { 
    $xml = simplexml_load_file ($file); 
    return (peelTags ($xml , array())); 
} 
function peelTags($node, $tag) { 
// find if there are children. (IF SO, there shouldn't be 
$numChildren = @count ($node->children()); 

if ($numChildren != 0) { 
    foreach ($node->children() as $child) { 
     $tag [] = $child->getName(); 
     peelTags ($child, $tag); 

     echo "<br />Name = " . $child->getName(); 
    } 
} 
    return $tag; 
} 

$file = "dictionarytest.xml"; 
print_r (ripXML ($file)); 

EDIT 2 - я понял это окончательно. Это может быть немного грязно, а не лучший способ сделать это, но он решил проблему, с которой мне пришлось столкнуться. Если кому-то понадобится нечто подобное, вот оно!

$_SESSION ["a"] = array(); 
$_SESSION ["c"] = 0; 
function ripXML($file) { 
$xml = simplexml_load_file ($file); 
return (peelTags ($xml, array())); 
} 
function peelTags($node, $tag) { 
// find if there are children. (IF SO, there shouldn't be 
$numChildren = @count ($node->children()); 

if ($numChildren != 0) { 
    foreach ($node->children() as $child) { 
     peelTags ($child, $tag); 
     $tag = $child->getName(); 
     if ($tag == "literal") { 
      $_SESSION ["c"] ++; 
     } 
     $value = trim($child->__toString()); 
     if (isset ($value) && $value != "") { 
      if ($child->attributes()) { 
       foreach ($child->attributes() as $k => $v) { 
        if (isset ($v) && $v != "") { 
         $_SESSION ["a"] [$_SESSION ["c"]] [$k . "_" . $v] = $value; 
        } 
       } 
      } else { 
       $_SESSION ["a"] [$_SESSION ["c"]] [$tag] = $value; 
      } 
     } 
    } 
} 
return 1; 
} 

$file = "dictionarytest.xml"; 
print_r (ripXML ($file)); 
print_r ($_SESSION ["a"]); 

Я использовал глобальные переменные сеанса для хранения массива и счетчика для рекурсивного алгоритма. Я не знаю, есть ли у кого-то лучшее предложение. Я хотел бы оптимизировать эту функцию, если это возможно. Я тестировал его в XML-файле всего 5 записей, но у моего реального файла будет более 4000.

+0

http://php.net/dom узнать, что –

+0

Пожалуйста, покажите код, который вы пробовали и почему оно не работает. То, что вы хотите сделать, возможно. –

+0

Вам нужны атрибуты и значения в определенном порядке? – blissini

ответ

1

... смущает. Я не синтаксическую проверку или проверить это, но я думаю, что его что-то вроде этого ..

$domd=new DOMDocument(); 
$domd->loadXML($xml); 
$interestingdomnode=$domd->getElementsByTagName("character")->item(0); 
$parsed_info=array(); 
$parsed_info['literal']=$interestingdomnode->getElementsByTagName("literal")->item(0)->textContent; 
foreach($interestingdomnode->getElementsByTagName("cp_value") as $cp){ 
$parsed_info["cp_type-".$cp->cp_type]=$cp->textContent 
} 
foreach($interestingdomnode->getElementsByTagName("rad_type") as $cp){ 
$parsed_info["rad_type-".$cp->rad_type]=$cp->textContent 
} 
$parsed_info['meaning']=''; 
foreach($interestingdomnode->getElementsByTagName("meaning") as $cp){ 
$parsed_info['meaning'].=$cp->textContent.PHP_EOL; 
} 
var_dump($parsed_info); 
+0

Что-то по этим строкам будет работать, но, к сожалению, я имею дело с узлами, которые могут иметь больше или меньше полей , разные имена и т. д., поэтому я не хотел жестко кодировать структуру. Я хотел чего-то более абстрактного и гибкого. – KiaiFighter

+0

oh..sorry, я слишком устал, чтобы понять это, но я думаю, вам нужно зациклиться на $ domnode-> attributes – hanshenrik

+0

Я понял это сейчас! Спасибо за вдохновение! – KiaiFighter

Смежные вопросы