用PHP为Wordpress产品列表解析XML


Parsing XML with PHP for Wordpress Product List

我正在尝试用PHP解析一个XML文件,以便替换某个标记的值。

这就是相关XML的样子:

<channel>
    <item>
        <title>Woo Logo</title>
        <link>http://demo2.woothemes.com/woocommerce/product/woo-logo/</link>
        <pubDate>Fri, 07 Jun 2013 10:35:51 +0000</pubDate>
        <dc:creator>wooteam</dc:creator>
        <guid isPermaLink="false">http://demo2.woothemes.com/dummydata/?post_type=product&#038;p=15</guid>
        <description></description>
        <content:encoded><![CDATA[Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.]]></content:encoded>
        <excerpt:encoded><![CDATA[Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.]]></excerpt:encoded>
        <wp:post_id>15</wp:post_id>
        <wp:post_date>2013-06-07 10:35:51</wp:post_date>
        <wp:post_date_gmt>2013-06-07 10:35:51</wp:post_date_gmt>
        <wp:comment_status>open</wp:comment_status>
        <wp:ping_status>closed</wp:ping_status>
        <wp:post_name>woo-logo</wp:post_name>
        <wp:status>publish</wp:status>
        <wp:post_parent>0</wp:post_parent>
        <wp:menu_order>0</wp:menu_order>
        <wp:post_type>product</wp:post_type>
        <wp:post_password></wp:post_password>
        <wp:is_sticky>0</wp:is_sticky>
        <category domain="product_cat" nicename="clothing"><![CDATA[Clothing]]></category>
        <category domain="product_type" nicename="simple"><![CDATA[simple]]></category>
        <category domain="product_cat" nicename="t-shirts"><![CDATA[T-shirts]]></category>
        <wp:postmeta>
            <wp:meta_key>_edit_last</wp:meta_key>
            <wp:meta_value><![CDATA[3]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_thumbnail_id</wp:meta_key>
            <wp:meta_value><![CDATA[16]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_visibility</wp:meta_key>
            <wp:meta_value><![CDATA[visible]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_stock_status</wp:meta_key>
            <wp:meta_value><![CDATA[instock]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>total_sales</wp:meta_key>
            <wp:meta_value><![CDATA[0]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_downloadable</wp:meta_key>
            <wp:meta_value><![CDATA[no]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_virtual</wp:meta_key>
            <wp:meta_value><![CDATA[no]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_product_image_gallery</wp:meta_key>
            <wp:meta_value><![CDATA[17]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_regular_price</wp:meta_key>
            <wp:meta_value><![CDATA[20]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_sale_price</wp:meta_key>
            <wp:meta_value><![CDATA[18]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_tax_status</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_tax_class</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_purchase_note</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_featured</wp:meta_key>
            <wp:meta_value><![CDATA[no]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_weight</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_length</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_width</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_height</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_sku</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_product_attributes</wp:meta_key>
            <wp:meta_value><![CDATA[a:0:{}]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_sale_price_dates_from</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_sale_price_dates_to</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_price</wp:meta_key>
            <wp:meta_value><![CDATA[18]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_sold_individually</wp:meta_key>
            <wp:meta_value><![CDATA[]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_stock</wp:meta_key>
            <wp:meta_value><![CDATA[5]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_backorders</wp:meta_key>
            <wp:meta_value><![CDATA[no]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_manage_stock</wp:meta_key>
            <wp:meta_value><![CDATA[yes]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_upsell_ids</wp:meta_key>
            <wp:meta_value><![CDATA[a:1:{i:0;s:2:"60";}]]></wp:meta_value>
        </wp:postmeta>
        <wp:comment>
            <wp:comment_id>13</wp:comment_id>
            <wp:comment_author><![CDATA[Cobus Bester]]></wp:comment_author>
            <wp:comment_author_email>bester.c@gmail.com</wp:comment_author_email>
            <wp:comment_author_url></wp:comment_author_url>
            <wp:comment_author_IP>196.215.9.147</wp:comment_author_IP>
            <wp:comment_date>2013-06-07 11:57:05</wp:comment_date>
            <wp:comment_date_gmt>2013-06-07 11:57:05</wp:comment_date_gmt>
            <wp:comment_content><![CDATA[Simple and effective design. One of my favorites.]]></wp:comment_content>
            <wp:comment_approved>1</wp:comment_approved>
            <wp:comment_type></wp:comment_type>
            <wp:comment_parent>0</wp:comment_parent>
            <wp:comment_user_id>0</wp:comment_user_id>
            <wp:commentmeta>
                <wp:meta_key>akismet_error</wp:meta_key>
                <wp:meta_value><![CDATA[1370606225]]></wp:meta_value>
            </wp:commentmeta>
            <wp:commentmeta>
                <wp:meta_key>akismet_history</wp:meta_key>
                <wp:meta_value><![CDATA[a:4:{s:4:"time";d:1370606225.6765859127044677734375;s:7:"message";s:92:"Akismet was unable to check this comment (response: ), will automatically retry again later.";s:5:"event";s:11:"check-error";s:4:"user";s:0:"";}]]></wp:meta_value>
            </wp:commentmeta>
            <wp:commentmeta>
                <wp:meta_key>akismet_as_submitted</wp:meta_key>
                <wp:meta_value><![CDATA[a:67:{s:15:"comment_post_ID";i:15;s:14:"comment_author";s:12:"Cobus Bester";s:20:"comment_author_email";s:18:"bester.c@gmail.com";s:18:"comment_author_url";N;s:15:"comment_content";s:49:"Simple and effective design. One of my favorites.";s:12:"comment_type";s:0:"";s:14:"comment_parent";i:0;s:7:"user_ID";i:0;s:7:"user_ip";s:13:"196.215.9.147";s:10:"user_agent";s:119:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31";s:8:"referrer";s:56:"http://demo2.woothemes.com/woocommerce/product/woo-logo/";s:4:"blog";s:38:"http://demo2.woothemes.com/woocommerce";s:9:"blog_lang";s:5:"en_US";s:12:"blog_charset";s:5:"UTF-8";s:9:"permalink";s:56:"http://demo2.woothemes.com/woocommerce/product/woo-logo/";s:21:"akismet_comment_nonce";s:6:"passed";s:11:"POST_author";s:12:"Cobus Bester";s:10:"POST_email";s:18:"bester.c@gmail.com";s:11:"POST_rating";s:1:"4";s:12:"POST_comment";s:49:"Simple and effective design. One of my favorites.";s:7:"POST__n";s:10:"a80bd2f042";s:21:"POST__wp_http_referer";s:30:"/woocommerce/product/woo-logo/";s:11:"POST_submit";s:13:"Submit Review";s:20:"POST_comment_post_ID";s:2:"15";s:19:"POST_comment_parent";s:1:"0";s:26:"POST_akismet_comment_nonce";s:10:"bbd941e9bf";s:15:"SERVER_SOFTWARE";s:6:"Apache";s:11:"REQUEST_URI";s:33:"/woocommerce/wp-comments-post.php";s:15:"REDIRECT_IS_WPE";s:1:"1";s:27:"REDIRECT_WPE_CAN_WRITE_DISK";s:1:"0";s:15:"REDIRECT_STATUS";s:3:"200";s:6:"IS_WPE";s:1:"1";s:18:"WPE_CAN_WRITE_DISK";s:1:"0";s:9:"HTTP_HOST";s:19:"demo2.woothemes.com";s:13:"HTTP_X_LB_KEY";s:8:"woodemo2";s:13:"HTTP_X_IS_BOT";s:1:"0";s:15:"HTTP_USER_AGENT";s:119:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31";s:15:"HTTP_CONNECTION";s:5:"close";s:14:"CONTENT_LENGTH";s:3:"273";s:18:"HTTP_CACHE_CONTROL";s:9:"max-age=0";s:11:"HTTP_ACCEPT";s:63:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";s:11:"HTTP_ORIGIN";s:26:"http://demo2.woothemes.com";s:12:"CONTENT_TYPE";s:33:"application/x-www-form-urlencoded";s:12:"HTTP_REFERER";s:56:"http://demo2.woothemes.com/woocommerce/product/woo-logo/";s:20:"HTTP_ACCEPT_ENCODING";s:17:"gzip,deflate,sdch";s:20:"HTTP_ACCEPT_LANGUAGE";s:14:"en-US,en;q=0.8";s:19:"HTTP_ACCEPT_CHARSET";s:30:"ISO-8859-1,utf-8;q=0.7,*;q=0.3";s:11:"HTTP_COOKIE";s:0:"";s:4:"PATH";s:28:"/usr/local/bin:/usr/bin:/bin";s:16:"SERVER_SIGNATURE";s:0:"";s:11:"SERVER_NAME";s:19:"demo2.woothemes.com";s:11:"SERVER_ADDR";s:9:"127.0.0.1";s:11:"SERVER_PORT";s:2:"80";s:11:"REMOTE_ADDR";s:13:"196.215.9.147";s:13:"DOCUMENT_ROOT";s:26:"/nas/wp/www/sites/woodemo2";s:12:"SERVER_ADMIN";s:18:"[no address given]";s:15:"SCRIPT_FILENAME";s:47:"/nas/wp/www/sites/woodemo2/wp-comments-post.php";s:11:"REMOTE_PORT";s:5:"57596";s:12:"REDIRECT_URL";s:33:"/woocommerce/wp-comments-post.php";s:17:"GATEWAY_INTERFACE";s:7:"CGI/1.1";s:15:"SERVER_PROTOCOL";s:8:"HTTP/1.0";s:14:"REQUEST_METHOD";s:4:"POST";s:12:"QUERY_STRING";s:0:"";s:11:"SCRIPT_NAME";s:21:"/wp-comments-post.php";s:8:"PHP_SELF";s:21:"/wp-comments-post.php";s:12:"REQUEST_TIME";s:10:"1370606225";s:25:"comment_post_modified_gmt";s:19:"2013-06-07 11:15:25";}]]></wp:meta_value>
            </wp:commentmeta>
            <wp:commentmeta>
                <wp:meta_key>rating</wp:meta_key>
                <wp:meta_value><![CDATA[4]]></wp:meta_value>
            </wp:commentmeta>
            <wp:commentmeta>
                <wp:meta_key>akismet_history</wp:meta_key>
                <wp:meta_value><![CDATA[a:4:{s:4:"time";d:1370607940.89634990692138671875;s:7:"message";s:46:"wooteam changed the comment status to approved";s:5:"event";s:15:"status-approved";s:4:"user";s:7:"wooteam";}]]></wp:meta_value>
            </wp:commentmeta>
        </wp:comment>
    </item>
</channel>

我对与价格有关的wp:postmeta块感兴趣——有<wp:meta_key>_price</wp:meta_key>的块。以下是我尝试做的:

$dom=new DOMDocument();
$dom->load("/var/www/wp-content/plugins/woocommerce/dummy-data/nspro.xml");
$root=$dom->documentElement;
$markers=$root->getElementsByTagName('item');
echo $markers->item(0)->getElementsByTagName('wp:postmeta')->item(22)->getElementsByTagName('wp:meta_key')->item(0)->textContent;

这不起作用-我得到这个错误:

Fatal error: Call to a member function getElementsByTagName() on a non-object.

错误是在$markers->item(0)->getElementsByTagName('wp:postmeta')->item(22)->之后引用带有该函数的调用。显然,我不能像引用列表中的第一个<item>那样使用它。如何访问<wp:postmeta>块内部的标签?

您没有在示例XML中发布相关内容。document元素包含名称空间定义(xmlns:*属性)。您要查找的数据位于xmlns:wp属性定义的命名空间中。

您可以使用Xpath以更简单、更稳定的方式获取数据。

$dom = new DOMDocument();
$dom->loadXML($xml);
// create an XPath instance
$xpath = new DOMXpath($dom);
// register a prefix for the wordpress export namespace
$xpath->registerNamespace('wp', 'http://wordpress.org/export/1.0/');
// fetch all rss item element nodes and iterate them
foreach ($xpath->evaluate('//item') as $item) {
  // get the price meta data as a number
  var_dump(
    $xpath->evaluate(
      'number(.//wp:postmeta[wp:meta_key = "_price"]/wp:meta_value)',
      $item
    )
  );
}

演示:https://eval.in/188516

输出:

float(18)

现在,如果您想编辑某个内容,您需要将其作为节点获取。如果Xpath表达式是一个位置路径,它将始终返回一个节点列表,就像getElementsByTagName()一样。您可以检查列表是否包含值,但我更喜欢在Xpath中进行限制,只使用foreach()。

// inside the item loop
$priceNodes = $xpath->evaluate(
  './/wp:postmeta[wp:meta_key = "_price"][1]/wp:meta_value', $item
);
foreach ($priceNodes as $priceNode) {
  $newPrice = 42; 
  $priceNode->nodeValue = (int)$newPrice;
}

演示:https://eval.in/188529

注意使用DOMNode::$nodeValue。仅设置不能包含&的值。PHP有一个错误。否则,使用它可以删除所有子节点并附加一个新的文本节点。

$priceNode->nodeValue = '';
$priceNode->appendChild($dom->createTextNode($newPrice));

所以这应该有效:

$xml = file_get_contents('/var/www/wp-content/plugins/woocommerce/dummy-data/nspro.xml');
$content = simplexml_load_string($xml);
echo $content->item->postmeta[22]->meta_key;

我对您有问题的代码的输出是:

_price