Reputation: 4783
I am making a XMPP PHP client and currently while in testing phase I have made stanzas (i.e. presence) like this:
const PRESENCE = <<<PRESENCE
<presence from="{from}" to="{to}" type="{type}" />
PRESENCE;
const PRIORITY = <<<PRIORITY
<presence from="{from}">
<priority>{priority}</priority>
</presence>
PRIORITY;
However while developing a library I wanted to do it somewhat programatically as I feel this approach looks like it's hardcoded even though I do parse it like this for example:
$preparedString = str_replace(
['{from}', '{priority}'],
[$from, $priority],
Xml::PRIORITY
);
So I ended up creating a Presence
class which should hold all presence related methods and act as a sort of an XML builder, and it looks like this:
private $instance = null;
public function __construct()
{
$this->instance = new \DOMDocument();
$this->instance->formatOutput = true;
}
public function requestPresence(string $from, string $to, string $type = "subscribe")
{
$presenceNode = $this->instance->createElement('presence');
$presenceNode->setAttribute("from", $from);
$presenceNode->setAttribute("to", $to);
$presenceNode->setAttribute("type", $type);
return $this->instance->saveXML($presenceNode);
}
public function setPriority(int $priority, string $from = null)
{
$presenceNode = $this->instance->createElement('presence');
if ($from)
$presenceNode->setAttribute("from", $from);
$priorityNode = $this->instance->createElement('priority');
$priorityNode->appendChild($this->instance->createTextNode($priority));
$presenceNode->appendChild($priorityNode);
return $this->instance->saveXML($presenceNode);
}
But now I have some doubts as I have tripled my code and it was actually more readable before. I would like to keep it simple and effective and without code duplication, but I feel like I'm missing something here. Is there a more slick way to do this?
Upvotes: 0
Views: 45
Reputation: 57121
DOMDocument is a more verbose interface for XML, you could use SimpleXML which will reduce the boiler plate code.
class XML {
public static function requestPresence(string $from, string $to, string $type = "subscribe")
{
$instance = new SimpleXMLElement("<presence />");
$instance["from"] = $from;
$instance["to"] = $to;
$instance["type"] = $type;
return $instance->asXML();
}
public static function setPriority(int $priority, string $from = null)
{
$instance = new SimpleXMLElement("<presence />");
if ($from) {
$instance["from"] = $from;
}
$instance->priority = $priority;
return $instance->asXML();
}
}
This assumes that they are two separate requirements and they are just utility functions rather than having to maintain any state.
If you need to build a document with more options then the following may be more useful...
class XML2 {
private $instance = null;
public function __construct() {
$this->instance = new SimpleXMLElement("<presence />");
}
public function requestPresence(string $from, string $to, string $type = "subscribe")
{
$this->instance["from"] = $from;
$this->instance["to"] = $to;
$this->instance["type"] = $type;
return $this;
}
public function setPriority(int $priority, string $from = null)
{
if ($from) {
$this->instance["from"] = $from;
}
$this->instance->priority = $priority;
return $this;
}
public function getXML() {
return $this->instance->asXML();
}
}
which called using...
echo (new XML2())->requestPresence("from", "to", "type")
->setPriority(1)
->getXML();
creates...
<?xml version="1.0"?>
<presence from="from" to="to" type="type"><priority>1</priority></presence>
Using DOMDocument or SimpleXML solutions will feel more bloated than your original version - but will provide a more robust solution which is more maintainable than relying on string handling.
Upvotes: 1