問題のリストを取得するために、YouTrack の Web サービスにクエリを実行しています。応答は、次のような XML です。
<issueCompacts>
<issue id="XX-1">
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>Bug</value>
</field>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Bill-to">
<value>NBS</value>
</field>
</issue>
<issue id="XX-2">
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>New Feature</value>
</field>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Bill-to">
<value>NBS</value>
</field>
</issue>
[...]
</issueCompacts>
この XML には実際には 5 つの問題が含まれており、そこから $issuesObj という名前の SimpleXMLElement オブジェクトを作成します (複数形の「問題」に注意してください)。次に、問題を繰り返します。
foreach ($issuesObj as $issueObj) {
[...]
} //foreach
このループ内 (as 変数の特異な「issue」に注意してください) で、var_dump() $issueObj を実行すると、次のようになります。
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["id"]=>
string(4) "XX-1"
}
["field"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#16 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
[1]=>
object(SimpleXMLElement)#17 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(7) "Bill-to"
}
["value"]=>
string(3) "NBS"
}
}
}
$issueObj->asXml() のダンプは次のとおりです。
<?xml version="1.0"?>
<issue id="XX-1">
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>Bug</value>
</field>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Bill-to">
<value>NBS</value>
</field>
</issue>
これまでのところ、これはまさに予想どおりです。しかし、ここが変なところです。名前が「タイプ」である課題内のフィールドを選択したいので、xpath() メソッドを使用しています。
$typeField = $issueObj->xpath('//field[@name="Type"]')
$typeField をダンプすると、次のようになります。
array(5) {
[0]=>
object(SimpleXMLElement)#10 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
[1]=>
object(SimpleXMLElement)#11 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(11) "New Feature"
}
[2]=>
object(SimpleXMLElement)#13 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(11) "New Feature"
}
[3]=>
object(SimpleXMLElement)#14 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
[4]=>
object(SimpleXMLElement)#15 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(11) "New Feature"
}
}
予想される 2 つではなく、5 つの要素があることに注意してください。起こっているように見えるのは、xpath() メソッドが、サブセットである $issueObj ではなく、元の $issuesObj に作用していることです。しかし、それはさらに奇妙になります。$issueObj を XML に変換し、その XML を使用してオブジェクトに戻ると、うまくいきます。したがって:
$issueObj = new \SimpleXMLElement($issueObj->asXml());
$typeField = $issueObj->xpath('//field[@name="Type"]');
var_dump($typeField); exit;
これが得られます:
array(1) {
[0]=>
object(SimpleXMLElement)#17 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(4) "Type"
}
["value"]=>
string(3) "Bug"
}
}
どちらが正しい。$typeField[0]->asXml() を呼び出すと、次のようになります。
<?xml version="1.0"?>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CustomField" name="Type">
<value>Bug</value>
</field>
これも、まったく予想どおりです。
SimpleXMLElement がこのように動作している理由についての手がかりはありますか?