如何控制XMPP XML

How to control XMPP XML

我正在制作一个 XMPP PHP client,目前在测试阶段我制作了这样的节(即存在):

    const PRESENCE = <<<PRESENCE
<presence from="{from}" to="{to}" type="{type}" />
PRESENCE;

    const PRIORITY = <<<PRIORITY
<presence from="{from}">
    <priority>{priority}</priority>
</presence>
PRIORITY;

然而,在开发一个库时,我想以某种方式进行编程,因为我觉得这种方法看起来像是硬编码的,即使我确实像这样解析它,例如:

$preparedString = str_replace(
    ['{from}', '{priority}'],
    [$from, $priority],
    Xml::PRIORITY
);

所以我最终创建了一个 Presence class 它应该包含所有与存在相关的方法并充当一种 XML 构建器,它看起来像这样:

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);
}

但现在我有一些疑问,因为我的代码增加了三倍,而且它实际上比以前更具可读性。我想让它保持简单有效并且没有代码重复,但我觉得我在这里遗漏了一些东西。有没有更巧妙的方法来做到这一点?

DOMDocument 是 XML 的更详细的接口,您可以使用 SimpleXML 来减少样板代码。

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();
    }
}

这假设它们是两个独立的需求,并且它们只是实用函数而不是必须维护任何状态。

如果您需要构建包含更多选项的文档,那么以下内容可能更有用...

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();
    }
}

调用使用...

echo  (new XML2())->requestPresence("from", "to", "type")
    ->setPriority(1)
    ->getXML();

创建...

<?xml version="1.0"?>
<presence from="from" to="to" type="type"><priority>1</priority></presence>

使用 DOMDocument 或 SimpleXML 解决方案会感觉比原始版本更臃肿 - 但会提供更强大的解决方案,比依赖字符串处理更易于维护。