【问题标题】:How to send custom XML data using the Smack library?如何使用 Smack 库发送自定义 XML 数据?
【发布时间】:2011-09-17 07:02:18
【问题描述】:

我正在使用 Java 中的 Smack API 连接到我的 XMPP 服务器。

我想发送一个这样的自定义消息包:

<message to="you@MyServer.com" type="chat" MYFIELD="custom stuff">
    <body> hi </body>
    <CUSTOM_STANZA A="..." B="..."> 
        C="..." 
        D="..."
    </CUSTOM_STANZA>
</message>

我猜我创建了实现我自己的 Packet 并在它的 toXML() 方法中返回这个 XML。但这似乎不起作用。

任何帮助将不胜感激。

【问题讨论】:

  • As mentioned by Robin:永远不要将自定义属性添加到顶级节元素。另见XEP-134。这是一个经常犯的错误。
  • 如何不重要,为什么重要。你不应该这样做!

标签: java xml xmpp smack


【解决方案1】:

您需要定义一个自定义类,该类应该实现 ExtensionElement(如@Flow 所述)

可以在in this answer获得一个非常详细的解释,产生以下节。

<message id='923442621149' type='chat'><body>shanraisshan</body>
<reply xmlns='shayan:reply' rText='this is custom attribute'/>
</message>

其中 reply 是自定义扩展,其中包含

  1. 元素(回复)
  2. 命名空间 (shayan:reply)

默认 xmpp 命名空间列表位于 Official XMPP website

【讨论】:

  • 不,自定义类应该实现 ExtensionElement
【解决方案2】:

您可以为此使用packet extension:不幸的是,没有很好的文档或示例来使用数据包扩展。我之前看过this unresolved question,它有示例代码,但我无法让它工作:我没有例外,但它根本不起作用,因为我的扩展没有被调用,我继续将我的数据编码为消息的正文。

编辑:为了后代,我设法使以下代码正常工作。它使用 DOM4J 类 DocumentHelperElement

Presence np, packet = new Presence();
        packet.setID(sessionManager.nextStreamID().toString());
        packet.setFrom(server.createJID(operator, null));
        if(!available) packet.setType(Presence.Type.unavailable);
        else packet.setType(null);

        // add the custom XML
        Element xml = DocumentHelper.createElement(QName.get("custom", "http://www.custom.com/xmpp"));
        xml.addAttribute("type", "presenceupdate");
        packet.addExtension(new PacketExtension(xml));

有点幽默:一年后我遇到了自己的答案,当时我实际上是在尝试为一个真正的项目解决这个问题(而不是像以前那样修补),因为我不能放弃它,所以我必须弄清楚出去。我想我会再次需要这个答案,所以就在这里。 SO:我在天空中的记忆。

编辑:找到了一种更简单的方法:

        Element xml = packet.addChildElement("custom", "http://www.custom.com/xmpp");
        xml.addAttribute("type", "presenceupdate");

注意事项:尝试添加某些内容(在我的情况下,尝试添加 delay 元素)导致数据包未被路由。 Openfire 中的某些东西吞噬了它,因此需要注意这一点。

【讨论】:

  • 当我添加一个数据包扩展时,我可以添加我的&lt;CUSTOM_STANZA ...&gt;,这样就可以了。但我真正想做的是编辑消息节以拥有MYFIELD="custom stuff"。在我的一生中,我无法弄清楚如何自定义此消息标题以包含我的自定义字段。
  • Openfire 似乎丢弃了一些空包。在正文中添加一些非空白文本。
【解决方案3】:

我最近发现了如何将自定义节添加到您的消息中。一旦我弄清楚了,这很容易。我只需要使用我的自定义消息类扩展标准消息类。

public class CustomMessage extends org.jivesoftware.smack.packet.Message {
  public CustomMessage() {
    super();
  }

  private String customStanza;

  /**
   * @param customStanza
   *            the customStanza to set
   */
  public void setCustomStanza(String customStanza) {
    this.customStanza = customStanza;
  }

  @Override
  public String toXML() {
    String XMLMessage = super.toXML();
    String XMLMessage1 = XMLMessage.substring(0, XMLMessage.indexOf(">"));
    String XMLMessage2 = XMLMessage.substring(XMLMessage.indexOf(">"));
    if (this.customStanza != null) {
      XMLMessage1 += " CustomStanza=\"" + this.customStanza + "\"";
    }

    return XMLMessage1 + XMLMessage2;
  }
}

然后使用自定义类发送这样的消息:

CustomMessage message = new CustomMessage();
message.setCustomStanza("my data here");
System.out.println(message.toXML());
muc.sendMessage(message);

您的 XML 消息将如下所示:

<message id="ee7Y7-8" CustomStanza="my data here"></message>

【讨论】:

  • 这是了解自定义节创建的最佳答案。帮了我很多...Thnx 伙计们。
  • 从不继承 Smack 的 Message。如果你认为你需要这样做,那你就做错了。 Message 旨在通过使用 PacketExtension 进行扩展
  • org.jivesoftware.smack.packet.Message 现在是 Final class。 ...public final class Message extends Stanza implements TypedCloneable&lt;Message&gt;.
【解决方案4】:

我不知道您为什么要在消息中添加自定义属性。这在客户端会出现问题,并且可能会在服务器上导致问题,因为它与消息节的架构不匹配。

另一方面,消息内容很容易处理,正如@Femi 所说,带有数据包扩展名。您需要创建一个扩展 PacketExtension 的 MyExtension,该类中的 toXML() 将返回您的自定义节。

您可以通过以下方式创建和发送自定义消息:

Message message = new Message();
message.addExtension(new MyExtension());
chat.sendMessage(message);

要阅读该节,您需要注册一个provider,它将创建并返回您的自定义 PacketExtension。你应该看看EmbeddedExtensionProvider,因为它会为你处理标签解析,从而简化了过程。

【讨论】:

  • 我想在此上下文中指出xmpp.org/extensions/xep-0134.html#xmpp,这解释了为什么添加自定义消息属性是个坏主意。
  • 嗨罗宾,我能知道这个新的 MyExtension() 是什么吗?可以提供那个类
猜你喜欢
  • 2016-12-11
  • 1970-01-01
  • 2019-04-03
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
相关资源
最近更新 更多