<?php
$xpath = "/bids_offers/market_submit/sem_gen_technical_offer/block_deloading/point[2]";
$xml = new EformDOMDocument();
$root = $xml->createElement("bids_offers");
$xml->appendChild($root);
$xml->buildMissingTree($xpath);
$xml->formatOutput = true;
echo $xml->saveXML();
class EformDOMDocument extends DOMDocument {
public $xpath;
public function __construct($version = null, $encoding = null) {
parent::__construct($version, $encoding);
$this->xpath = new DOMXPath($this);
}
public function setAttributeX($path, $attributeName, $attributeValue) {
// check if path returns anything valid
if ($this->xpath->query($path)->length == 0) {
$this->buildMissingTree($path);
}
$this->xpath->query($path)->item(0)->setAttribute($attributeName, $attributeValue);
}
public function buildMissingTree($path) {
$missingNodes = array();
$tempPath = $path;
// build an array of missing elements in the path
while ($this->xpath->query($tempPath)->length == 0) {
$tempName = basename($tempPath);
$tempPath = dirname($tempPath);
// deal with such: testnode[@type='HOT'] or [#]
if (strpos($tempName, '[') === FALSE) {
// no attributes use $tempName
$missingNodes[] = $this->createElement($tempName);
} else {
// split element name and attribute, create both separate, append attribute to element, push into the aray
$tempHolder = explode('[', $tempName);
$tempElement = $this->createElement($tempHolder[0]);
// [1] is attribute, clean it up, split name and value
if (strpos($tempHolder[1], '@') !== FALSE) {
// element has attiribute if it has @ in the path piece
$attParam = str_replace(array('@', '\'', ']'), '', $tempHolder[1]);
$attribute = explode('=', $attParam);
$tempElement->setAttribute($attribute[0], $attribute[1]);
} // otherwise its a number of the node in the sequence, skip it, as if xml is generated is in order,
//previous nodes should exist already
$missingNodes[] = $tempElement;
$tempElement = null;
}
}
// build the structure with missing elements (use $missingNodes array)
// get existing end
echo $tempPath;
var_dump($missingNodes[0]);
$currentElement = $this->xpath->query($tempPath)->item(0);
while (($newElement = array_pop($missingNodes)) !== NULL) {
$currentElement->appendChild($newElement);
$currentElement = $newElement;
}
}
/**
* Checks if document has at least one element with a name (and optional attribute) provided
*
* @param string $name
* @return mixed
*/
public function hasElement($name, $attribute = '') {
$elements = $this->getElementsByTagName($name);
if ($elements->length > 0) {
if ($attribute == '') {
return true;
}
// if attribute provided, check through the list for the element with provided attribute
for ($i = 0; $i < $elements->length; $i++) {
// TODO fix that checks on attibute value too, not just name
if ($elements->item($i)->hasAttribute($attribute)) {
return $elements->item($i);
//return true;
}
}
}
return false;
}
/**
*
* @param string $name
* @param string $attributeParameters provided as "attr1name=value1;attr2name=value2...etc."
* @return DOMElement
*/
public function createElementWithAttributes($name, $attributeParameters = '') {
$element = $this->createElement($name);
// atributes provided as "attr1name=value1;attr2name=value2...etc."
if ($attributeParameters != '') {
// separate multiple parameters
$attributes = explode(';', $attributeParameters);
// add parameters to the element
foreach ($attributes as $attribute) {
$keyvalue = explode('=', $attribute);
$element->setAttribute($keyvalue[0], $keyvalue[1]);
}
}
return $element;
}
}