PHP Conference Japan 2024

SimpleXMLElement::addAttribute

(PHP 5 >= 5.1.3, PHP 7, PHP 8)

SimpleXMLElement::addAttribute 新增屬性至 SimpleXML 元素

說明

public SimpleXMLElement::addAttribute(字串 $qualifiedName, 字串 $value, ?字串 $namespace = null):

為 SimpleXML 元素新增一個屬性。

參數

qualifiedName

要新增的屬性名稱。

value

屬性的值。

namespace

如果指定,則為屬性所屬的命名空間。

回傳值

無回傳值。

範例

注意事項:

列出的範例可能包含 example.php,它指的是在基本用法指南第一個範例中的 XML 字串。

範例 #1 為 SimpleXML 元素新增屬性和子元素

<?php

include 'example.php';

$sxe = new SimpleXMLElement($xmlstr);
$sxe->addAttribute('type', 'documentary');

$movie = $sxe->addChild('movie');
$movie->addChild('title', 'PHP2: More Parser Stories');
$movie->addChild('plot', 'This is all about the people who make it work.');

$characters = $movie->addChild('characters');
$character = $characters->addChild('character');
$character->addChild('name', 'Mr. Parser');
$character->addChild('actor', 'John Doe');

$rating = $movie->addChild('rating', '5');
$rating->addAttribute('type', 'stars');

echo
$sxe->asXML();

?>

上述範例將輸出類似以下的內容

<?xml version="1.0" standalone="yes"?>
<movies type="documentary">
 <movie>
  <title>PHP: Behind the Parser</title>
  <characters>
   <character>
    <name>Ms. Coder</name>
    <actor>Onlivia Actora</actor>
   </character>
   <character>
    <name>Mr. Coder</name>
    <actor>El Act&#xD3;r</actor>
   </character>
  </characters>
  <plot>
   So, this language. It's like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  </plot>
  <great-lines>
   <line>PHP solves all my web problems</line>
  </great-lines>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
 <movie>
  <title>PHP2: More Parser Stories</title>
  <plot>This is all about the people who make it work.</plot>
  <characters>
   <character>
    <name>Mr. Parser</name>
    <actor>John Doe</actor>
   </character>
  </characters>
  <rating type="stars">5</rating>
 </movie>
</movies>

另請參閱

新增註釋

使用者貢獻的註釋 7 則註釋

Patanjali
8 年前
您無法使用這個方法來更新現有屬性的值。

請改為取得 SimpleXMLElement 的 DOM 版本,並使用 setAttribute 方法,如下所示:

$XML = '<element a="aa">Text</element>';
$snode = new simple_xml_element($XML);

$dnode = dom_import_simplexml($snode);
$dnode->setAttribute('a', 'bb');

產生的節點 XML 為
<element a="bb">Text</element>
booleer at yahoo dot it
13 年前
如果屬性已經存在,addAttribute 不會執行任何動作。

範例
<?php
$xml_string
= <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="foo">
<root>
XML;

$xml = simplexml_load_string($xml_string);
$xml->item->addAttribute('id', 'bar');
echo
$xml->asXML();
?>

上述範例將輸出
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="foo">
<root>
caffeinatedbits
1 年前
剛發現另一個好用的技巧。需要移除屬性嗎?也很簡單!

<?php

$xml
= <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog breed="chihuahua"/>
</Animals>
EOF;

$animals = new SimpleXMLElement($xml);

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua"/>

unset($animals->Dog['breed']);

echo
$animals->Dog->asXML();
// <Dog/>

?>
caffeinatedbits
1 年前
我需要一個方法來更新屬性,但我找不到任何說明文件記載如何做到這一點。

經過多次實驗後,以下是我找到可行的方法 - 答案如此簡單,我花了 8 次嘗試才發現 :-)

以下列範例來說

<?php

$xml
= <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog/>
</Animals>
EOF;

$animals = new SimpleXMLElement($xml);

echo
$animals->Dog->asXML();
// <Dog/>

?>

測試 #6 - 或許可以直接像陣列一樣修改 attributes() Iterator,它會偷偷呼叫 __set() 魔術方法?

簡而言之:是的

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

$dogAttrs = $animals->Dog->attributes();
// object(SimpleXMLElement)#4 (1) {
// ["@attributes"]=>
// array(1) {
// ["breed"]=>
// string(9) "chihuahua"
// }
// }

$dogAttrs['breed'] = "poodle";
// 可以運作!

echo $animals->Dog->asXML();
// <Dog breed="poodle">

?>

測試 #7 - 或許我根本不需要呼叫 attributes()?

簡而言之:確實不需要!

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

$animals->Dog['breed'] = "poodle";
// 可以運作!

echo $animals->Dog->asXML();
// <Dog breed="poodle">

?>

測試 #8 - 或許我一開始就不需要呼叫 addAttribute()?

簡而言之:是的,我可以完全跳過它!

<?php

...

$animals->Dog['breed'] = "chihuahua";
// 成功!

echo $animals->Dog->asXML();
// <Dog breed="chihuahua">

$animals->Dog['breed'] = "poodle";
// 成功!

echo $animals->Dog->asXML();
// <Dog breed="poodle">

?>

補充說明:我也提交了另一份獨立的筆記,說明哪些方法無效,以防您像我一樣好奇並想嘗試其他方法。
p.servus
13 年前
如果您需要命名空間,則必須將命名空間的前綴加上屬性名稱(「前綴:名稱」)作為第一個參數,並將 URI 作為第三個參數。(我不知道為什麼?!)

範例程式碼
<?php
$xml
= new SimpleXMLElement("<packagedElement></packagedElement>");
$xml->addAttribute("xmi:type", "uml:Class", "http://schema.omg.org/spec/XMI/2.1");
echo
$xml->asXml();
?>

輸出
<packagedElement xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmi:type="uml:Class"></packagedElement>
caffeinatedbits
1 年前
我需要一個方法來更新屬性,但我找不到任何說明文件記載如何做到這一點。

簡而言之:這不僅可行,而且非常簡單。請參閱我提交的另一份筆記,了解實際有效的方法(抱歉,由於 4095 個字元的限制,我無法將所有內容都放在一份筆記中)。

經過多次實驗,以下是我發現無效的方法;希望它能為您節省我所花費的時間和精力。

以下列範例來說

<?php

$xml
= <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog/>
</Animals>
EOF;

$animals = new SimpleXMLElement($xml);

echo
$animals->Dog->asXML();
// <Dog/>

?>

測試 #1 - 嘗試呼叫 addAttribute() 兩次

簡而言之:PHP 警告:SimpleXMLElement::addAttribute(): 屬性已存在

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua"/>

$animals->Dog->addAttribute('breed', "poodle");
// PHP 警告:SimpleXMLElement::addAttribute(): 屬性已存在

echo $animals->Dog->asXML();
// <Dog breed="chihuahua"/>

?>

測試 #2 - 嘗試以傳址方式迭代 attributes()(一個迭代器)

簡而言之:迭代器不能與 foreach 的傳址方式一起使用

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

try {
foreach (
$animals->Dog->attributes() as $attr => &$value) {
if (
"breed" === $attr) {
$value = "poodle";
}
}
} catch (
Throwable $e) {
echo
$e->getMessage();
// 無法以傳參考方式使用迭代器搭配 foreach
}

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

?>

測試 #3 - 嘗試重新解析子元素,然後在重新解析的元素上呼叫 addAttribute(),如我在這裡找到的註釋中建議的

簡而言之:PHP 警告:SimpleXMLElement::addAttribute(): 屬性已存在

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

$animals->Dog = new SimpleXMLElement($animals->asXML());

$animals->Dog->addAttribute('breed', "poodle");
// PHP 警告:SimpleXMLElement::addAttribute(): 屬性已存在

echo $animals->Dog->asXML();
// <Dog breed="chihuahua">

?>

測試 #4 - 嘗試修改 @attributes 陣列元素

簡而言之:PHP 通知:間接修改 SimpleXMLElement 的重載元素無效

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

$dogAttrs = $animals->Dog->attributes();
// object(SimpleXMLElement)#4 (1) {
// ["@attributes"]=>
// array(1) {
// ["breed"]=>
// string(9) "chihuahua"
// }
// }

$dogAttrs['@attributes']['breed'] = "poodle";
// PHP 通知:間接修改 SimpleXMLElement 的重載元素無效

echo $animals->Dog->asXML();
// <Dog breed="chihuahua">

?>

測試 #5 - 將 attributes() 轉換為陣列並設定 'breed' 元素的值

簡而言之:不會更新原始物件中的值

<?php

...

$animals->Dog->addAttribute('breed', "chihuahua");

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

$dogAttrs = (array) $animals->Dog->attributes();
// array(1) {
// ["@attributes"]=>
// array(1) {
// ["breed"]=>
// string(9) "chihuahua"
// }
// }

$dogAttrs['@attributes']['breed'] = "poodle";

echo
$animals->Dog->asXML();
// <Dog breed="chihuahua">

?>
sarlak
13 年前
您可以用這種方式透過名稱來存取節點的子節點:

<?php
$root
= new SimpleXMLElement($filePath);
echo
$root->nodeName->attributes;

// 它可以遞迴運作,所以以下程式碼也能正常執行
echo $root->nodeName->subNodeName->attributes();
?>

但如果您想要新增屬性到子節點,您**必須**使用 children() 方法來存取和修改它,否則它會修改父節點的屬性。

<?php
// 新增一個子節點
$element->nodeName->addChild('subNodeName', "whatever you want");

// 取得子節點在父節點中的位置
$lastNodePos = $element->nodeName->count()-1;

// 取得父節點的子節點們
$nodeChildrens = $element->nodeName->children();

// 新增一個屬性到最後建立的子節點
$nodeChildrens[$lastNodePos]->addAttribute('attributeName', "The attribute value);
?>
To Top