SimpleXML声明了xmlns:xmlns =“” - 无法删除

时间:2011-07-08 15:56:44

标签: php xml rss simplexml xml-namespaces

令人气愤,我几乎无法说话。我已经使用SimpleXML组装了一个RSS提要 - 但它正在使用名称空间,现在就是这样。但是,当输出时,它会不断尝试在根节点中声明xmlns:xmlns =“”。即使我不这样做。

开头
$rssXML->addAttribute("version", '2.0');
$rssXML->addAttribute("xmlns:media", "http://search.yahoo.com/mrss/", '');
$rssXML->addAttribute("xmlns:dcterms", "http://purl.org/dc/terms/", '');

之后我做了: -

header("Content-Type: application/rss+xml");

echo $syndicationXML->asXML();

然而它输出: -

<?xml version="1.0"?>
<rss xmlns:xmlns="" version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/"><channel>...

我不明白所有这个名称空间声明。发生了什么事?

3 个答案:

答案 0 :(得分:7)

SimpleXML的问题在于它的addAttribute函数添加了一个属性,而不是一个命名空间,虽然它看起来像你想要的那样,但它并不意味着以你使用它的方式使用。

这意味着添加一个特定命名空间(指定为第三个参数)的值,而不是添加命名空间本身。您最终使用xmlns:xmlns的原因是因为SimpleXML发现您在指定名称xmlns时使用了xmlns:media命名空间,因此它创建了一个空xmlns:xmlns

以下是您的问题的两种解决方案:

<强> 1。在构造函数的命名空间中指定。

$rssXML = new SimpleXMLElement('<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/" />');
$rssXML->addAttribute('version', '2.0');

<强> 2。使用xmlns:xmlns=""

替换preg_replace
echo preg_replace('/xmlns:xmlns=""\s?/', '', $rssXML->asXML());

答案 1 :(得分:1)

您写道,您要删除它。最好的方法是不要把它放在第一位。

这通过前缀xmlns:(另一次)起作用 - 它以某种方式在simplexml中启用特殊操作模式 - 而提供空命名空间URI(否则你实际上要求补充说明):

$rssXML = new SimpleXMLElement('<rss/>');
$rssXML->addAttribute("version", '2.0');
$rssXML->addAttribute("xmlns:xmlns:media", "http://search.yahoo.com/mrss/");
$rssXML->addAttribute("xmlns:xmlns:dcterms", "http://purl.org/dc/terms/");
$rssXML->asXML('php://output');

这会创建以下输出(为了您的阅读乐趣而美化):

<?xml version="1.0"?>
<rss version="2.0" 
     xmlns:media="http://search.yahoo.com/mrss/" 
     xmlns:dcterms="http://purl.org/dc/terms/"/>

这个“作弊”最初是在"Unable to add Attribute with Namespace Prefix using PHP Simplexml"中暗示的,但在这里不见了。

答案 2 :(得分:1)

SimpleXMLElement只能间接添加名称空间。由于您只能添加元素和属性节点,而不能添加名称空间声明,文本节点或其他节点类型,因此您必须以某种方式使用SimpleXMLElement->addAttribute()SimpleXMLElement->addChild()。后者只会为孩子添加新的命名空间,所以在这里没用。 addAttribute()会将命名空间和属性添加到给定元素中,因此,如果您删除该属性,则根据需要留下命名空间。

没有一种明显的删除属性的方法,但使用unset如#34; Remove a child with a specific attribute, in SimpleXML for PHP&#34;的几个答案所示。可以使用SimpleXMLElement->attributes()来获取对属性的引用,以适应任务。

<?php
$rssXML = new SimpleXMLElement('<rss/>');
$rssXML->addAttribute("version", '2.0');
# add a dummy attribute to get the namespace
$rssXML->addAttribute("media:_", '', "http://search.yahoo.com/mrss/");
unset($rssXML->attributes('media', TRUE)[0]);
# and again
$rssXML->addAttribute("dcterms:_", '', "http://purl.org/dc/terms/");
unset($rssXML->attributes('dcterms', TRUE)[0]);

echo $rssXML->asXML(), "\n";

结果:

<?xml version="1.0"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/" version="2.0"/>

这优于将名称空间声明添加为前缀为伪名称空间的属性,它被视为名称空间,而不是恰好在其名称中看起来像名称空间前缀的属性。

var_export($rssXML->getDocNamespaces());

结果:

array (
  'media' => 'http://search.yahoo.com/mrss/',
  'dcterms' => 'http://purl.org/dc/terms/',
)