【问题标题】:SimpleXML has declaration of xmlns:xmlns="" - no way to removeSimpleXML 声明了 xmlns:xmlns="" - 无法删除
【发布时间】:2011-10-01 09:51:14
【问题描述】:

太气人了,我几乎说不出话来。我已经用 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>...

我不明白所有这些命名空间声明。怎么回事?

【问题讨论】:

    标签: php xml rss simplexml xml-namespaces


    【解决方案1】:

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

    它的目的是添加一个属于特定命名空间的值(指定为第三个参数),而不是添加命名空间本身。你最终得到xmlns:xmlns的原因是因为SimpleXML发现你在指定名称xmlns:media时使用了xmlns命名空间,所以它创建了一个空的xmlns:xmlns

    这里有 2 个解决您的问题的方法:

    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。用preg_replace替换xmlns:xmlns=""

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

    【讨论】:

    • 解释得很清楚,很有帮助,也很正确。谢谢你。 :)
    【解决方案2】:

    您写过要删除它。最好的方法是不要把它放在首位。

    这通过以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" 中暗示的,但在这里却不见了。

    【讨论】:

    • 之所以有效,是因为添加的节点是一个属性,而不是命名空间声明,并且“xmlns:”是属性名称的本地部分的一部分,而不是命名空间前缀。您可以使用任何前缀,而不仅仅是“xmlns”,因为它会被忽略。序列化时无关紧要,但在使用对象时会有所不同(例如,使用 SimpleXMLElement-&gt;attributes()SimpleXMLElement-&gt;children() 的参数,或 SimpleXMLElement-&gt;addChild() 的命名空间参数)。
    【解决方案3】:

    SimpleXMLElement 只能间接添加命名空间。由于您只能添加元素和属性节点,而不是命名空间声明、文本节点或其他节点类型,因此您必须以某种方式使用SimpleXMLElement-&gt;addAttribute()SimpleXMLElement-&gt;addChild()。后者只会给孩子添加新的命名空间,所以在这里没有用。 addAttribute() 会将命名空间与属性一起添加到给定元素中,因此如果您随后删除该属性,您将获得所需的命名空间。

    没有明显的删除属性的方法,但是如“Remove a child with a specific attribute, in SimpleXML for PHP”的几个答案所示,unset 的使用可以适应任务,使用SimpleXMLElement-&gt;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/',
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-25
      • 2017-10-14
      • 1970-01-01
      • 2011-01-27
      相关资源
      最近更新 更多