如何在 XML 节点之前插入 g:

How to insert g: before XML node

我找到了这个帖子: How to write CDATA using SimpleXmlElement?

所以我通过关注创建了一个 XML 提要。

例如它 returns 我是这样的:

<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title>
<![CDATA[ Site title ]]>
</title>
<link>https://www.example.com</link>
<description>
<![CDATA[ Site description ]]>
</description>
<item>
 <id>ABCD</id>
 <title>
  <![CDATA[ Productname ]]>
 </title>
 <description>
  <![CDATA[ Product description ]]>
 </description>
 <gtin>
  <![CDATA[ ]]>
 </gtin>
 <mpn>
  <![CDATA[ 3305 ]]>
 </mpn>
</item>
</channel>
</rss>

我如何设法使 <gtin><mpn> 变为:

<g:gtin><g:mpn>

这是我的 php 代码:

<?php

class SimpleXMLExtended extends SimpleXMLElement {
  public function addCData($cdata_text) {
    $node = dom_import_simplexml($this); 
    $no   = $node->ownerDocument; 
    $node->appendChild($no->createCDATASection($cdata_text)); 
  } 
}

$xmlFile    = 'feed_nl.xml';
$xml        = new SimpleXMLExtended('<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0"/>');
$channel = $xml->addChild('channel');
$channel->title = NULL;
$channel->title->addCData('Site title');

$channel->addChild('link', "https://www.example.com/");

$channel->description = NULL;
$channel->description->addCData('Site description');

$query = new WP_Query( array(
    'post_type'      => 'product',
    'post_status'    => 'publish',
    'posts_per_page' => -1,
    'suppress_filters' => false
) );

while ( $query->have_posts() ) : $query->the_post();

    $post_id = get_the_ID();
    $product = wc_get_product( $post_id );
    $product_title = get_the_title();
    $product_description = get_the_excerpt();
    $mpn = $product->get_sku();
    $gtin = get_field('barcode');


    $item->title = NULL;
    $item->title->addCData($product_title);

    $item->description = NULL;
    $item->description->addCData($product_description);

    $item->gtin = NULL;
    $item->gtin->addCData($gtin);

    $item->mpn = NULL;
    $item->mpn->addCData($mpn);

endwhile;

$xml->saveXML($xmlFile);

?>

最终代码:

<?php

class SimpleXMLElementExtended extends SimpleXMLElement{
    public function addChildWithCDATA($name , $value, $google) {
        if ($google) {
            $new = parent::addChild($name, '', $google);
        } else {
            $new = parent::addChild($name);
        }
        $base = dom_import_simplexml($new);
        $docOwner = $base->ownerDocument;
        $base->appendChild($docOwner->createCDATASection($value));
    }
}

$GOOGLE_BASE_NS = 'http://base.google.com/ns/1.0';

$xmlFile    = 'feed_test.xml';
// instead of $xml = new SimpleXMLElement('<site/>');
$xml = new SimpleXMLElementExtended(
  '<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0"/>'
);
$channel = $xml->addChild('channel');

$channel->addChildWithCDATA('title', 'Site title', '');

$channel->addChild('link', "https://www.example.com");

$query = new WP_Query( array(
    'post_type'      => 'product',
    'post_status'    => 'publish',
    'posts_per_page' => 1,
    'suppress_filters' => false
) );

while ( $query->have_posts() ) : $query->the_post();

    $post_id = get_the_ID();
    $product = wc_get_product( $post_id );
    $product_title = get_the_title();
    $product_description = get_the_excerpt();
    $product_link = get_the_permalink();
    $product_link = $product_link . "?source=googlebase";
    $product_thumbnail_url = get_the_post_thumbnail_url();
    $attachment_ids = $product->get_gallery_image_ids();
    $availability = $product->get_availability();
    $availability = $availability['class'];
    $availability = str_replace('-', ' ', $availability);
    $price = $product->get_price();
    if (empty($price)) {$price = '0.00';}
    $price = $price . " EUR";
    $mpn = $product->get_sku();
    $gtin = get_field('barcode');

    $item = $channel->addChild('item', '', '');
    $item->addChild('id', $post_id, $GOOGLE_BASE_NS);

    $item->addChild('link', $product_link);
    $item->addChild('image_link', $product_thumbnail_url, $GOOGLE_BASE_NS);
    foreach( $attachment_ids as $attachment_id ) {
        $image_link = wp_get_attachment_url( $attachment_id );
        $item->addChild('additional_image_link', $image_link, $GOOGLE_BASE_NS);
    }
    $item->addChild('availability', $availability, $GOOGLE_BASE_NS);
    $item->addChild('price', $price, $GOOGLE_BASE_NS);
    $item->addChild('condition', "new", $GOOGLE_BASE_NS);
    
    $item->addChildWithCDATA('gtin', $gtin, $GOOGLE_BASE_NS);

endwhile;

$xml->saveXML($xmlFile);
?>

XML中用冒号分隔的前缀是命名空间的别名。检查最近的 xmlns:* 的祖先节点。这是别名的定义。

XML 解析器会将以下所有示例读取为 {http://base.google.com/ns/1.0}gtin

  • <gtin xmlns="http://base.google.com/ns/1.0}gtin"/>
  • <g:gtin xmlns:g="http://base.google.com/ns/1.0}gtin"/>
  • <google:gtin xmlns:google="http://base.google.com/ns/1.0}gtin"/>

要创建具有命名空间的元素节点,您必须提供命名空间。对于 SimpleXMLElement::addChild(),这是第三个参数。前缀是节点名称的一部分 - 第一个参数。

// define a constant for the namespace uri literal
const GOOGLE_BASE_NS = 'http://base.google.com/ns/1.0';

$rss = new SimpleXMLElement(
  '<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0"/>'
);
// implicit namespace handling - can inherit
$channel = $rss->addChild('channel');
// explicit no namespace 
$item = $channel->addChild('item', '', '');

// explicit namespace with prefix 
$item->addChild('g:gtin', 'example', GOOGLE_BASE_NS);

echo $rss->asXML();