2

大規模な XML ドキュメントを解析していますが、子ノードの解析に関して多くの問題を抱えています。以下は、私が解析しようとしているもののサンプルです。

<link rel="http://xxxxx/people.employees" title="employees">
    <people>
      <link href="/154" rel="http://catalog/person" title="Guy Nom" />
      <link href="/385" rel="http://catalog/person" title="Carrie Jin" />
      <link href="/162" rel="http://catalog/person" title="Joe Zee" />
      <link href="/2125" rel="http://catalog/person" title="Mark Polin" />
      <link href="/9293" rel="http://catalog/person" title="Stephen Castor" />
      <link href="/21822" rel="http://catalog/person" title="Callum Tinge" />
      <link href="/2022" rel="http://catalog/person" title="Brian Lennon" />
      <link href="/2040" rel="http://catalog/person" title="Jorja Fox" />
      <link href="/2046" rel="http://catalog/person" title="Harry Harris" />
      <link href="/2399" rel="http://catalog/person" title="Sam Muellerleile" />
    </people>
  </link>
  <link rel="http://xxxxx/people/others" title="others">
    <people>
      <link href="/7143" rel="http://catalog/person" title="James Smith" />
    </people>
  </link>

「従業員」と「その他」を区別して、別のフィールドに保存する必要があります。私は以下のようなことをしたい:

if($xmlReader->localName == 'link') {
    if ($xmlReader->getAttribute('title') == "employees"){
      //GO TO NEXT LINK TAG AND GET NAME
      $myObject->employees[$myObject->employees_count]['name'] = $xmlReader->getAttribute('title');
      $myObject->employees_count++;

    } else if ($xmlReader->getAttribute('title') == "others"){
      //GO TO NEXT LINK TAG AND GET NAME
      $myObject->others[$myObject->others_count]['name'] = $xmlReader->getAttribute('title');
      $myObject->others_count++;

    }
  }

明らかに、上でコメントされているビットは私にとって問題です。私はこれらの子要素の読み方を知りません。私の意見では、これに関する PHP ドキュメントはまったく優れていません。助けていただければ幸いです。

4

3 に答える 3

2

XMLReader::readInnerXML() を使用する

<?php
$reader = new XMLReader();
$reader->open("filename.xml");

while ($reader->read()) {

    if($reader->name=='Foo' && $reader->nodeType == XMLReader::ELEMENT) {

        $reader->moveToElement();
        $Foo = new SimpleXMLElement($reader->readOuterXml());

        //$Foo->bar

    }
}
$reader->close();
?>
于 2013-11-21T06:40:43.293 に答える
2

$depthXmlReader の場合、プロパティを利用できます。<link>要素は have (one)のようになるので、読み進めている間に、現在の要素がまだその子である1かどうかを確認できます。END_ELEMENT$depth

昨日の回答で、次のように拡張してそのロジックをカプセル化する方法を示しましたXML_Reader

親要素の深さを、readToNextChildElement($depth)子要素のみをトラバースできる新しいメソッドに渡すことができます。

使用例:

$depth = $reader->depth; # parent elements depth
while ($reader->readToNextChildElement($depth)) {
    # only children
}

実装は次のとおりです。

class MyXMLReader extends XMLReader
{
    ...

    public function readToNextChildElement($depth)
    {
        // if the current element is the parent and
        // empty there are no children to go into
        if ($this->depth == $depth && $this->isEmptyElement) {
            return false;
        }

        while ($result = $this->read()) {
            if ($this->depth <= $depth) return false;
            if ($this->nodeType === self::ELEMENT) break;
        }

        return $result;
    }

    ...

リンクされた回答で残りのコードを見つけることができます。必要に応じて、これが役立つ場合があります-これXML_Readerをベースにしたい場合。それ以外の場合は、代わりにドキュメント全体をメモリに読み込むことができれば、Xpath を使用して要素をクエリする方がはるかに簡単です。

$employees_names = array_map(
    'strval', 
    $sxml->xpath('//link[@title="employees"]//link/@title')
);

それがSimpleXMLでした。

于 2013-02-17T08:07:25.140 に答える
1

個人的にはSimpleXML、XMLReaderは十分に文書化されていないため、これを使用します。(ニーズに応じて)XMLReaderが文書の他の部分を解析するために適切に機能していない場合は、うまく機能するはずです。そうは言っても、これが私が使用したコードと入力です。

test.xml

<?xml version="1.0" encoding="UTF-8" ?>
<result>
<link rel="http://xxxxx/people.employees" title="employees">
    <people>
        <link href="/154" rel="http://catalog/person" title="Guy Nom" />
        <link href="/385" rel="http://catalog/person" title="Carrie Jin" />
        <link href="/162" rel="http://catalog/person" title="Joe Zee" />
        <link href="/2125" rel="http://catalog/person" title="Mark Polin" />
        <link href="/9293" rel="http://catalog/person" title="Stephen Castor" />
        <link href="/21822" rel="http://catalog/person" title="Callum Tinge" />
        <link href="/2022" rel="http://catalog/person" title="Brian Lennon" />
        <link href="/2040" rel="http://catalog/person" title="Jorja Fox" />
        <link href="/2046" rel="http://catalog/person" title="Harry Harris" />
        <link href="/2399" rel="http://catalog/person" title="Sam Muellerleile" />
    </people>
</link>
<link rel="http://xxxxx/people/others" title="others">
    <people>
        <link href="/7143" rel="http://catalog/person" title="James Smith" />
    </people>
</link>
</result>

次に、そのサンプルをPHPで解析します(注:ここには変数が含まれていませんが、これから必要なものを導き出すことができるはずです。また、最後に、何が行われたかを検証、つまり表示します。設定されています。)

<?php

$xml = simplexml_load_file('test.xml','SimpleXMLElement', LIBXML_NOCDATA);
//Place holder variables as I don't have access to the object.
$emp=array();$emp_count=0;$other=array();$other_count=0;

foreach($xml->link as $links) {
    $at = $links->attributes();
    if($at['title'] == 'employees') {
        foreach($links->people->link as $person) {
            $emp_count++;
            $employee = $person->attributes();
            $emp[] = (string)$employee['title'];
        }
    } elseif($at['title'] == 'others') {
        foreach($links->people->link as $person) {
            $other_count++;
            $others = $person->attributes();
            $other[] = (string)$others['title'];
        }
    }
}
echo "<pre>";
echo "Employees: $emp_count\n";
print_r($emp);

echo "Others: $other_count\n";
print_r($other);

echo "</pre>";
?>

そしてこれが出力でした(自分で実行する必要はありません^^)

Employees: 10
Array
(
    [0] => Guy Nom
    [1] => Carrie Jin
    [2] => Joe Zee
    [3] => Mark Polin
    [4] => Stephen Castor
    [5] => Callum Tinge
    [6] => Brian Lennon
    [7] => Jorja Fox
    [8] => Harry Harris
    [9] => Sam Muellerleile
)
Others: 1
Array
(
    [0] => James Smith
)

お役に立てば幸いです。

于 2013-02-17T05:20:02.513 に答える