在 PHP 中使用 SimpleXML 按属性添加新创建的子 xml 元素给出错误 "Attribute already exists" 错误

Adding child newly created xml element by attribute using SimpleXML in PHP gives error "Attribute already exists" error

我想为这个 xml 文档创建两个 'Style' 子项,然后向它们添加子项。示例:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
    <Style id="red">
        <LineStyle>
            <color>ff0000ff</color>
            <width>1</width>
        </LineStyle>
        <PolyStyle>
            <color>110000ff</color>
        </PolyStyle>
    </Style>
    <Style id="blue">
        <LineStyle>
            <color>ffff0000</color>
            <width>1</width>
        </LineStyle>
        <PolyStyle>
            <color>11ff0000</color>
        </PolyStyle>
    </Style>
</Document>
</kml>

但是,我收到错误

SimpleXMLElement::addAttribute(): Attribute already exists in...

$xmlstr = <<<EOL
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"/>
EOL;

$xml = new SimpleXMLElement($xmlstr);
$xml->addChild("Document");

$xml->Document->addChild("Style");
$xml->Document->Style->addAttribute("id", "red");
$xml->Document->Style->addChild("PolyStyle");
$xml->Document->Style->PolyStyle->AddChild("color", "110000ff"); # opacity,bbggrr
$xml->Document->Style->addChild("LineStyle");
$xml->Document->Style->LineStyle->AddChild("color", "ff0000ff"); # opacity,bbggrr
$xml->Document->Style->LineStyle->AddChild("width", "1");

$xml->Document->addChild("Style");
$xml->Document->Style->addAttribute("id", "blue");
$xml->Document->Style->addChild("PolyStyle");
$xml->Document->Style->PolyStyle->AddChild("color", "11ff0000"); # opacity,bbggrr
$xml->Document->Style->addChild("LineStyle");
$xml->Document->Style->LineStyle->AddChild("color", "ffff0000"); # opacity,bbggrr
$xml->Document->Style->LineStyle->AddChild("width", "1");

我认为解决方案是使用 xpath 查找我刚刚创建的元素:

$style = $xml->xpath('Style[@id="red"]');
$style[0]->addChild("LineStyle");

但是 $style 是空的 returns

Call to a member function addChild() on null

问题是虽然你调用

$xml->Document->addChild("Style");

两次添加新的样式元素,你总是用

设置细节
$xml->Document->Style->addAttribute("id", "red");

执行此方法将始终等同于在第一个 Style 元素上设置 id 属性(当找到 Style 中的多个元素时,它将始终假定为第一个元素)。所以你第二次这样做(使用"id", "blue"),它从第一次调用时就已经存在(设置为"red")。

更好的方法是存储 addChild() 中的 return 值,然后在此元素中设置详细信息...

$style2 = $xml->Document->addChild("Style");
$style2->addAttribute("id", "blue");
$style2->addChild("PolyStyle");

等等

您的 XPath 表达式的问题是您尝试通过一个属性来识别它,在您找到节点之前无法添加该属性 - 这有点尴尬。你可以做...

$xml->Document->Style[1]->addAttribute("id", "red");

但这意味着要跟踪您创建的 Style 元素的数量并更新 [1] - 这有风险。