PHP SimpleXML: как использовать двоеточия в именах - PullRequest
13 голосов
/ 11 июня 2010

Я пытаюсь создать RSS Google Merchant, используя SimpleXML.

Пример, предоставленный Google:

<?xml version="1.0"?>
<rss version="2.0" 
xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>The name of your data feed</title>
<link>http://www.example.com</link>
<description>A description of your content</description>
<item>
<title>Red wool sweater</title>
<link> http://www.example.com/item1-info-page.html</link>
<description>Comfortable and soft, this sweater will keep you warm on those cold winter nights.</description>
<g:image_link>http://www.example.com/image1.jpg</g:image_link> <g:price>25</g:price> <g:condition>new</g:condition> <g:id>1a</g:id>
</item>
</channel>
</rss>

В моем коде есть такие вещи, как:

$product->addChild("g:condition", 'new');

, который генерирует:

<condition>new</condition>

Я прочитал в Интернете, что я должен вместо этого использовать:

$product->addChild("g:condition", 'new', 'http://base.google.com/ns/1.0');

, который теперь генерирует:

<g:condition xmlns:g="http://base.google.com/ns/1.0">new</g:condition>

Это кажется очень противоречивым-интуитивно для меня, так как теперь объявление "xmlns" присутствует почти в КАЖДОЙ строке моего RSS-канала, целых один раз в корневом элементе.

Я что-то упустил?

Ответы [ 3 ]

13 голосов
/ 27 ноября 2011

Как сказал @ceejayoz, вам нужно добавить пространство имен "http://base.google.com/ns/1.0"" к корневому узлу, чтобы SimpleXML знал, что пространство имен уже объявлено и не генерирует дублирующую привязку префикса.вам может понадобиться прочитать учебник по пространствам имен XML , потому что я не уверен, что вы действительно понимаете, что здесь делает "g:".

Вот более полный пример. XML:

$xml = <<<EOT 
<?xml version="1.0"?> 
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0"> 
  <channel> 
    <title>The name of your data feed</title> 
    <link>http://www.example.com</link> 
    <description>A description of your content</description> 
    <item> 
      <title>Red wool sweater</title> 
      <link> http://www.example.com/item1-info-page.html</link> 
      <description>Comfortable and soft, this sweater will keep you warm on those cold winter nights.</description> 
      <g:image_link>http://www.example.com/image1.jpg</g:image_link> 
      <g:price>25</g:price> 
      <g:id>1a</g:id> 
    </item> 
  </channel> 
</rss> 
EOT 
; 

Код:

$rss = new SimpleXMLElement($xml); 
$NS = array( 
    'g' => 'http://base.google.com/ns/1.0' 
); 
$rss->registerXPathNamespace('g', $NS['g']); 
$product = $rss->channel->item[0]; // example 

// Use the complete namespace. 
// Don't add "g" prefix to element name--what prefix will be used is 
// something SimpleXML takes care of. 
$product->addChild('condition', 'new', $NS['g']); 

echo $rss->asXML(); 

Обычно я использую этот шаблон, чтобы легко иметь дело с пространствами имен:

$rss = new SimpleXMLElement($xml); 
$NS = array( 
    'g' => 'http://base.google.com/ns/1.0' 
    // whatever other namespaces you want 
); 
// now register them all in the root 
foreach ($NS as $prefix => $name) { 
    $rss->registerXPathNamespace($prefix, $name); 
} 
// Then turn $NS to an object for more convenient syntax 
$NS = (object) $NS; 
// If I need the namespace name later, I access like so: 
$element->addChild('localName', 'Value', $NS->g); 
10 голосов
/ 06 января 2016

Это делает трюк:

$product->addChild('xmlns:g:condition', 'new'); 
1 голос
/ 11 июня 2010

Вам необходимо добавить это пространство имен в родительский узел, предпочтительно корневой rss, чтобы дочерние узлы могли его наследовать, вместо того чтобы каждый раз явно указывать его.

...