0

XML のノードを再帰的に json 文字列に変換する必要があります。私はほとんどの部分を持っています

$sku = "AC2061414";
$dom = new SimpleXMLElement(file_get_contents( "/usr/share//all_products.xml" )); 
$query = '//sku[text() = "'.$sku.'"]';
$entries = $dom->xpath($query);

foreach ($entries as $entry) {

    $parent_div = $entry->xpath( 'parent::*' );
    $nodearray=array();

    foreach($parent_div as $node) {
        if ($node->nodeType == XML_CDATA_SECTION_NODE) {
            $nodearray[$node->getName()]=$node->textContent;
        }else{
            $nodearray[$node->getName()]=$node;
        }
    }
    $ajax = json_encode( $nodearray );
    print($ajax);
}

走る

<?xml version="1.0" encoding="UTF-8"?>
<products>
   <product active="1" on_sale="0" discountable="1">
    <sku>AC2061414</sku>
    <name><![CDATA[ALOE CADABRA ORGANIC LUBE PINA COLADA 2.5OZ]]></name>
    <description><![CDATA[ text text ]]></description>
    <keywords/>
    <price>7.45</price>
    <stock_quantity>30</stock_quantity>
    <reorder_quantity>0</reorder_quantity>
    <height>5.25</height>
    <length>2.25</length>
    <diameter>0</diameter>
    <weight>0.27</weight>
    <color></color>
    <material>aloe vera, vitamin E</material>
    <barcode>826804006358</barcode>
    <release_date>2012-07-26</release_date>
    <images>
      <image>/AC2061414/AC2061414A.jpg</image>
    </images>
    <categories>
      <category code="528" video="0" parent="0">Lubricants</category>
      <category code="531" video="0" parent="528">Flavored</category>
      <category code="28" video="0" parent="25">Oral Products</category>
      <category code="532" video="0" parent="528">Natural</category>
    </categories>
    <manufacturer code="AC" video="0">Aloe Cadabra Lubes</manufacturer>
    <type code="LU" video="0">Lubes</type>
  </product>
</products>

そして、で終わります

{"product":{"@attributes":{"active":"1","on_sale":"0","discountable":"1"},"sku":"AC2061414","name":{},"description":{},"keywords":{},"price":"7.45","stock_quantity":"30","reorder_quantity":"0","height":"5.25","length":"2.25","diameter":"0","weight":"0.27","color":{},"material":"aloe vera, vitamin E","barcode":"826804006358","release_date":"2012-07-26","images":{"image":"\/AC2061414\/AC2061414A.jpg"},"categories":{"category":["Lubricants","Flavored","Oral Products","Natural"]},"manufacturer":"Aloe Cadabra Lubes","type":"Lubes"}}

CDATA であった欠落しているノード値を除いて、これは問題ないようです。私はそれを説明しようとしましたが、うまくいきません。ここでのトリックは何ですか?

4

2 に答える 2

1

ここでの問題はjson_encode、魔法のインターフェースに従って、あなたが持っている simplexml 要素を扱うためです。@attributesたとえば、シリアル化を参照してください。また、すべての child-cdata-nodes をスキップします。これは、要素の値をマジック モードで読み取るとき ( simplexmlelements の比較print_rと出力)、それらが削除されるためです。var_dump

CDATA ノードは周囲のテキストに正規化することも、単に共通のテキスト ノードに正規化することもできるため、SimpleXML では(または関数を使用したインスタンス化で) 正確にこれを行うためのLIBXML_NOCDATAオプションを提供しています。これらの CDATA ノードをテキスト ノードに変換し、それらのテキスト ノードを周囲にマージ存在する場合は text-nodes ( 「Merge CDATA as text nodes」 )。newsimplexml_load_*

これにより、ノード値がノード値になるためprint_rjson_encodeノード値が文字列 @attributes として返されます。これについては、 「PHP、SimpleXML、CDATA 内のエンティティのデコード」で (よく) 詳細に説明されています。

これに加えて、修正することで大きな利益を得られる別の誤解があります。属性値によって要素を選択するための xpath がコードに既に含まれていても、その親に直接関心があります。次に、SimpleXML は、すべての子に既に反復を提供します。の SimpleXML のマジック プロパティについても同様ですjson_encode。これによりコードをどのように削減できるかを比較してください。

$xml = simplexml_load_file("/usr/share/all_products.xml", NULL, LIBXML_NOCDATA); 

// NOTE: Prevent XPath Injection by not allowing " (or ') for 
//       SKU value (validate it against a whitelist of allowed
//       characters for example)
$sku   = "AC2061414";
$query = sprintf('(//sku[text() = "%s"])[1]/..', $sku); 

$products = $xml->xpath($query);

if ($products) {
    echo json_encode(["product" => $products[0]]);
}

デモを参照してください

これにより、実際にそれほど多くのコードを記述しなくても、同等の出力が得られるはずです。問題の (最初の) sku 要素 の親 ( ) ノードを直接LIBXML_NOCDATAクエリする、SimpleXMLElement を作成するときのオプションと、修正された xpath クエリを参照してください。次に、それが提供する魔法のプロパティの共通のトラバーサルにより、すべての子を処理します。<product>json_encode

同様に参照してください:

于 2013-07-08T12:29:38.263 に答える