3

ご存知の方もいらっしゃると思いますが、私はStackOverflowチャットシステムのXMPP(Jabber)統合に取り組んでいます。これは、xmpp4rパッケージを使用してRubyで記述されたXMPPコンポーネントです。

私は1つの問題に苦労しています(まあ、多くの問題がありますが、現時点では1つの問題です:-)チャットからJSONフィードを取得し、メッセージのHTMLを抽出しています。私はRubyTidyHTMLバインディングを使用してHTMLをXHTMLにフィードされたJSONから変換してXMPPメッセージとして送信できるようにしています-XMPPメッセージは単なるXMLであるため、HTMLをXHTMlに変換すると有効なXMLになります。<message>スタンザに固執するだけです。

ほとんどのメッセージでは、うまく機能します!

私の心は吹き飛ばされます

ただし、他のメッセージの場合は、完全にチョークします。XMPPサーバーがストリームを閉じ、スクリプトが停止します。(そして居酒屋のrchernと他の人は動揺します。まあ、動揺していないかもしれませんが、彼らは私を笑います。これは私を悲しくさせます!)

何らかの理由でメッセージが有効なXMLではないことが原因であるとほぼ確信しています。そのため、XMPPサーバーは、RubyコンポーネントからのXMLストリームで解析エラーが発生したため、接続を閉じています。このようなメッセージの例を次に示します。

<message to='jeswah@smart-safe-secure.com/Token' type='groupchat' xmlns='jabber:client'><body>&lt;div class=&quot;onebox ob-message&quot;&gt;&lt;a class=&quot;roomname&quot; href=&quot;/transcript/message/263372#263372&quot;&gt;&lt;span title=&quot;2010-11-04 19:20:23Z&quot;&gt;1 hour ago&lt;/span&gt;&lt;/a&gt;, by &lt;span class=&quot;user-name&quot;&gt;Fosco&lt;/span&gt; &lt;br/&gt;&lt;div class=&quot;quote&quot;&gt;&lt;div class=&quot;room-mini&quot;&gt;&lt;div class=&quot;room-mini-header&quot;&gt;&lt;h3&gt;&lt;img class=&quot;small-site-logo&quot; title=&quot;Gaming&quot; alt=&quot;Gaming&quot; width=&quot;16&quot; height=&quot;16&quot; src=&quot;http://sstatic.net/gaming/img/favicon.ico&quot; /&gt;&amp;nbsp;&lt;span class=&quot;room-name&quot;&gt;&lt;a href=&quot;http://chat.stackexchange.com/rooms/28/minecraft-talk&quot;&gt;Minecraft Talk&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;&lt;div class=&quot;room-mini-description&quot;&gt;Everything Minecraft, including classic and survival mode&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;room-current-user-count&quot; title=&quot;current users&quot;&gt;9&lt;/div&gt;&lt;div class=&quot;mspark&quot; style=&quot;height:25px;width:205px&quot;&gt;
&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:13px;left:0px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:9px;left:8px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:2px;left:16px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:8px;left:24px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:1px;left:32px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:1px;left:56px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:0px;left:64px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:0px;left:88px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:0px;left:96px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:11px;left:104px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:7px;left:112px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:7px;left:120px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:25px;left:128px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:14px;left:136px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:4px;left:144px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:7px;left:152px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:19px;left:160px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:19px;left:168px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:12px;left:176px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar&quot; style=&quot;width:8px;height:11px;left:184px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;mspbar now&quot; style=&quot;height:25px;left:154px;&quot;&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;clear-both&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</body><html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'><div class="onebox ob-message"><a class="roomname" href="/transcript/message/263372#263372"><span title="2010-11-04 19:20:23Z">1 hour ago</span></a>, by <span class="user-name">Fosco</span><br />
<div class="quote">
<div class="room-mini"><div class="room-mini-header">
<h3><img class="small-site-logo" title="Gaming" alt="Gaming" width="16" height="16" src="http://sstatic.net/gaming/img/favicon.ico" />&nbsp;<span class="room-name"><a href="http://chat.stackexchange.com/rooms/28/minecraft-talk">Minecraft Talk</a></span></h3>
<div class="room-mini-description">Everything Minecraft, including classic and survival mode</div>
</div>
<div class="room-current-user-count" title="current users">9</div>
<div class="mspark" style="height:25px;width:205px">
<div class="mspbar" style="width:8px;height:13px;left:0px;"></div>
<div class="mspbar" style="width:8px;height:9px;left:8px;"></div>
<div class="mspbar" style="width:8px;height:2px;left:16px;"></div>
<div class="mspbar" style="width:8px;height:8px;left:24px;"></div>
<div class="mspbar" style="width:8px;height:1px;left:32px;"></div>
<div class="mspbar" style="width:8px;height:1px;left:56px;"></div>
<div class="mspbar" style="width:8px;height:0px;left:64px;"></div>
<div class="mspbar" style="width:8px;height:0px;left:88px;"></div>
<div class="mspbar" style="width:8px;height:0px;left:96px;"></div>
<div class="mspbar" style="width:8px;height:11px;left:104px;"></div><div class="mspbar" style="width:8px;height:7px;left:112px;"></div><div class="mspbar" style="width:8px;height:7px;left:120px;"></div><div class="mspbar" style="width:8px;height:25px;left:128px;"></div><div class="mspbar" style="width:8px;height:14px;left:136px;"></div>
<div class="mspbar" style="width:8px;height:4px;left:144px;"></div>
<div class="mspbar" style="width:8px;height:7px;left:152px;"></div>
<div class="mspbar" style="width:8px;height:19px;left:160px;"></div>
<div class="mspbar" style="width:8px;height:19px;left:168px;"></div><div class="mspbar" style="width:8px;height:12px;left:176px;"></div>
<div class="mspbar" style="width:8px;height:11px;left:184px;"></div>
<div class="mspbar now" style="height:25px;left:154px;"></div>
</div>
<div class="clear-both"></div>
</div>
</div>
</div>
</body></html></message>

(このメッセージはたまたまチャットルームへのワンボックスリンクの引用でした)

これがRubyが私に与えたエラーでした:

IOError: stream closed
/usr/lib/ruby/1.8/xmpp4r/stream.rb:594:in `empty?'
/usr/lib/ruby/1.8/rexml/parsers/baseparser.rb:153:in `empty?'
/usr/lib/ruby/1.8/rexml/parsers/baseparser.rb:193:in `pull'
/usr/lib/ruby/1.8/rexml/parsers/sax2parser.rb:92:in `parse'
/usr/lib/ruby/1.8/xmpp4r/streamparser.rb:79:in `parse'
/usr/lib/ruby/1.8/xmpp4r/stream.rb:75:in `start'
/usr/lib/ruby/1.8/xmpp4r/stream.rb:72:in `initialize'
/usr/lib/ruby/1.8/xmpp4r/stream.rb:72:in `new'
/usr/lib/ruby/1.8/xmpp4r/stream.rb:72:in `start'
/usr/lib/ruby/1.8/xmpp4r/connection.rb:119:in `start'
/usr/lib/ruby/1.8/xmpp4r/component.rb:70:in `start'
/usr/lib/ruby/1.8/xmpp4r/connection.rb:77:in `connect'
/usr/lib/ruby/1.8/xmpp4r/component.rb:47:in `connect'
./classes/SOXMPP_Bridge.rb:20:in `initialize'
./soxmpp.rb:81:in `new'
./soxmpp.rb:81

最後に、私の質問です!

無効なXMLをXMPPサーバーに送信すると、XMPPサーバーに送信する前に、Rubyを使用してXMLを検証(およびできれば修正)できる方法はありますか?おそらく、それを修正するのは、Tidyが有効なXMLを生成していない場合ごとに追加のコードを書くことですが、少なくともスクリプトがクラッシュするのを防ぎたいと思います。では、XMLをXMPPサーバーに送信する前にXMLを検証するにはどうすればよいですか?

4

4 に答える 4

3

この場合の実際のエラーはあなた&nbsp;です。XEP-0071、セクション8、ポイント5によると:

XMPPコアのセクション11.1は、XML仕様のセクション4.6で定義されている5つの一般的なエンティティ(つまり、&lt;、&gt;、&amp;、&apos;、&quot;)以外の文字エンティティをXMLストリームで送信してはならないことを規定しています。 。したがって、XHTML-IMの実装には、&nbsp;などの事前定義されたXHTML1.0エンティティを含めてはなりません。--代わりに、実装はXML仕様のセクション4.1で指定されている同等の文字参照を使用する必要があります(「href」属性に含まれるURIなどの非自明な場所でも)。

したがって、この問題は、前提条件である整形式のXMLを生成するだけではありません。また、セクション6で承認されたセットのXHTMLのみを使用していることを確認する必要があります。

つまり、XEP-0071を読む必要があります。

于 2010-11-04T23:17:13.337 に答える
1

たぶん、実際にNokogiriを使用してXMLに変換することは役に立ちますか?その後、XMPPストリーム用に再シリアル化できます。また、コンテンツを少しスケーリングしてメモリの肥大化を回避したい場合は、XMPP4rではなくBlatherに切り替えてください。また、DSLはかなり素晴らしいです!

于 2010-11-04T21:33:15.290 に答える
1

* nixで実行していますか?もしそうなら、私は問題をlibxml2xmllintの一部であるプログラムに委任します。ネット経由で送信する前にxmlを生成するシステムを使用しています。次のように、xmllintを使用してxmlを検証します。

    command = "xmllint #{temp_file_path} --schema #{schema_file_path} --noout 2>&1"
    output = `#{command}`
    if $? != 0
      temp_dir.keep
      $stderr.puts "Error validating xml: running command #{command.inspect}"
      $stderr.puts output
      exit(1)
    end

もちろん、これを状況に適応させる必要がありますが、基本的な考え方はうまく機能します。DTDがない場合は、「-schema」ビットを省略してください。

于 2010-11-04T21:52:58.790 に答える
1

Tidyは使用しないでください。HTML5パーサーを使用して、生成されたDOMをXMLにダンプします。DOMを作成できれば、そのDOMから毎回整形式のXMLを作成できます。また、最新のブラウザで提供されるものとほぼ同じDOMを作成できるという利点もあります。

于 2010-11-04T22:00:35.560 に答える