从xml节点中删除属性

时间:2015-03-07 15:17:46

标签: php xml

我有一个像这样的RDF + XML文档:

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:void="http://rdfs.org/ns/void#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<void:linkset xmlns:void="void" xmlns:rdf="rdf" rdf:about="http://xxxxx/aa.rdf#1">
<void:subjectsTarget>a</void:subjectsTarget> 
<void:objectsTarget>b</void:objectsTarget>
<void:linkPredicate>c</void:linkPredicate>
<rdfs:comment xmlns:rdfs="rdfs"> comment... </rdfs:comment>
</void:linkset>
</rdf:RDF>

使用Symfony2框架中的SimpleXMLElement生成,代码如下:

        $rootNode = new \SimpleXMLElement('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:void="http://rdfs.org/ns/void#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" />');
        $about = 'http://xxxx/aa.rdf#a';
        $linksetNode = $rootNode->addChild('void:linkset','','void');
        $linksetNode->addAttribute("rdf:about",$about,"rdf");
        $linksetNode->addChild('void:subjectsTarget','a','void');
        $linksetNode->addChild('void:objectsTarget','b','void');
        $linksetNode->addChild('void:linkPredicate','c','void');            
        $linksetNode->addChild('rdfs:comment','comment...','rdfs');

任何人都可以帮我从节点void:linkset中删除xmlns:void和xmlns:rdf属性(名称空间),从rdfs:comment node中删除xmlns:rdfs属性(名称空间)?

我知道

$string = preg_replace('/xmlns:.*\"/','',$string);

但是这将从根节点rdf:RDF中删除xmlns命名空间我不想要的内容。

如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我认为你在这里混淆了一些XML命名空间,但我希望能够为你澄清这一点。

添加了xmlns:void="void"属性,因为您在此处命令simplexml执行此操作:

$linksetNode = $rootNode->addChild('void:linkset', '', 'void');

您添加void:linkset元素 前缀(&#34; void:&#34;在第一个参数的开头)提供一个新的(无效的)名称空间URI(第三个参数&#34; void&#34;)因此simplexml为该(无效)URI创建一个新的名称空间声明:

<void:linkset xmlns:void="void"/>

这样做,因为&#34; void:&#34;前缀已分配给URI&#34; http://rdfs.org/ns/void#&#34;,并且由于void前缀具有不同的名称空间含义,因此必须重新定义。重新定义是你不喜欢的属性。

所以这可以通过在现有命名空间中添加元素来解决:

$voidNsUri = "http://rdfs.org/ns/void#";
$linksetNode = $rootNode->addChild('linkset', '', $voidNsUri);

然后导致元素无需将名称空间前缀重新定义为新的(无效)URI:

<void:linkset>

将此转变为一个完全成熟的例子可能会产生以下结果:

$ns = [
    'rdf'  => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    'void' => 'http://rdfs.org/ns/void#',
    'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
];

$about = 'http://xxxx/aa.rdf#a';

$buffer  = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" />';
$xml     = new \SimpleXMLElement($buffer);
$linkset = $xml->addChild('linkset', '', $ns['void']);
$linkset->addAttribute("rdf:about", $about, $ns['rdf']);
$linkset->addChild('subjectsTarget', 'a', $ns['void']);
$linkset->addChild('objectsTarget', 'b', $ns['void']);
$linkset->addChild('linkPredicate', 'c', $ns['void']);
$linkset->addChild('comment', 'comment...', $ns['rdfs']);

echo tidy_repair_string($xml->asXML(), ['input-xml' => 1, 'indent' => 1, 'wrap' => 0]);

示范性的出局:

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <linkset xmlns="http://rdfs.org/ns/void#" rdf:about="http://xxxx/aa.rdf#a">
    <subjectsTarget>a</subjectsTarget>
    <objectsTarget>b</objectsTarget>
    <linkPredicate>c</linkPredicate>
    <comment xmlns="http://www.w3.org/2000/01/rdf-schema#">comment...</comment>
  </linkset>
</rdf:RDF>

如您所见,所有元素都在相应的命名空间中正确命名。命名空间定义放置在最适合的位置(这由XML库自动完成,该属性要求您明确指定它,因为该属性具有命名空间(第三个参数)属性不是元素,所以他们不在那里共享任何名称空间;比较Attributes and XML namespaces)。