You could loop through the elements and create a "new" xml. Something like this?
$xml = <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<elevate>
<query text="foo bar">
<doc id="1"/>
<doc id="2"/>
<doc id="3"/>
</query>
<query text="foo bar">
<doc id="4"/>
<doc id="9"/>
<doc id="3"/>
</query>
<query text="foo bar">
<doc id="4"/>
<doc id="8"/>
<doc id="3"/>
</query>
</elevate>
EOF;
$parsed = simplexml_load_string($xml);
$docs = [];
foreach ($parsed->query as $query) {
foreach ($query->doc as $doc) {
foreach ($doc->attributes() as $attribute) {
// you should do some checking here, like in_array to make sure there is no duplicates.
// we use __toString so it puts it as a string, not an XmlElement object
$docs[] = $attribute[0]->__toString();
}
}
}
$docsXml = '';
foreach ($docs as $doc) {
$docsXml .= '<doc id="' . $doc .'" />' . PHP_EOL;
}
$newXml = <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<elevate>
<query text="foo bar">
$docsXml
</query>
</elevate>
EOF;
echo $newXml;
Which outputs
<?xml version="1.0" encoding="UTF-8"?>
<elevate>
<query text="foo bar">
<doc id="1" />
<doc id="2" />
<doc id="3" />
<doc id="4" />
<doc id="9" />
<doc id="3" />
<doc id="4" />
<doc id="8" />
<doc id="3" />
</query>
</elevate>