Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[FEATURE] Parse NLSML documents and extract some useful information

  • Loading branch information...
commit af1c4c6df01ab2d4f169d0692bf92c35b541501f 1 parent b42b171
@benlangfeld authored
View
2  CHANGELOG.md
@@ -1,5 +1,5 @@
# [develop](https://github.com/benlangfeld/ruby_speech)
- * Feature: NLSML building
+ * Feature: NLSML building & parsing
# [1.0.2](https://github.com/benlangfeld/ruby_speech/compare/v1.0.1...v1.0.2) - [2012-12-26](https://rubygems.org/gems/ruby_speech/versions/1.0.2)
* Bugfix: Get test suite passing on JRuby
View
19 README.md
@@ -287,8 +287,23 @@ It's also possible to parse an NLSML document and extract useful information fro
document = RubySpeech.parse nlsml.to_s
document.match? # => true
-document.interpretations # => [#<RubySpeech::NLSML::Interpretation ...>, #<RubySpeech::NLSML::Interpretation ...>]
-document.best_interpretation # => #<RubySpeech::NLSML::Interpretation confidence=0.6 input=#<RubySpeech::NLSML::Input mode=:speech, text="I want to go to Pittsburgh"> model=#<RubySpeech::NLSML::Model ...> #<RubySpeech::NLSML::Instance ...>>
+document.interpretations # => [
+ {
+ confidence: 0.6,
+ input: { mode: :speech, content: 'I want to go to Pittsburgh' },
+ instance: { airline: { to_city: 'Pittsburgh' } }
+ },
+ {
+ confidence: 0.4,
+ input: { content: 'I want to go to Stockholm' },
+ instance: { airline: { to_city: 'Stockholm' } }
+ }
+ ]
+document.best_interpretation # => {
+ confidence: 0.6,
+ input: { mode: :speech, content: 'I want to go to Pittsburgh' },
+ instance: { airline: { to_city: 'Pittsburgh' } }
+ }
```
Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_speech/master/frames) for more
View
5 lib/ruby_speech.rb
@@ -18,6 +18,11 @@ module RubySpeech
autoload :NLSML
autoload :XML
end
+
+ def self.parse(string)
+ document = Nokogiri::XML.parse string, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS
+ NLSML::Document.new document
+ end
end
ActiveSupport::Autoload.eager_autoload!
View
1  lib/ruby_speech/nlsml.rb
@@ -4,6 +4,7 @@ module NLSML
eager_autoload do
autoload :Builder
+ autoload :Document
end
def self.draw(options = {}, &block)
View
75 lib/ruby_speech/nlsml/document.rb
@@ -0,0 +1,75 @@
+module RubySpeech
+ module NLSML
+ class Document
+ def initialize(xml)
+ @xml = xml
+ end
+
+ def grammar
+ result['grammar']
+ end
+
+ def interpretations
+ interpretation_nodes.map do |interpretation|
+ interpretation_hash_for_interpretation interpretation
+ end
+ end
+
+ def best_interpretation
+ interpretation_hash_for_interpretation interpretation_nodes.first
+ end
+
+ def match?
+ interpretation_nodes.count > 0
+ end
+
+ private
+
+ def input_hash_for_interpretation(interpretation)
+ input_element = interpretation.at_xpath 'input'
+ { content: input_element.content }.tap do |h|
+ h[:mode] = input_element['mode'].to_sym if input_element['mode']
+ end
+ end
+
+ def instance_hash_for_interpretation(interpretation)
+ instance_element = interpretation.at_xpath 'xf:instance'
+ element_children_key_value instance_element
+ end
+
+ def element_children_key_value(element)
+ element.children.inject({}) do |acc, child|
+ acc[child.node_name.to_sym] = case child.children.count
+ when 0
+ child.content
+ when 1
+ if child.children.first.is_a?(Nokogiri::XML::Text)
+ child.children.first.content
+ else
+ element_children_key_value child
+ end
+ else
+ element_children_key_value child
+ end
+ acc
+ end
+ end
+
+ def interpretation_hash_for_interpretation(interpretation)
+ {
+ confidence: interpretation['confidence'].to_f/100,
+ input: input_hash_for_interpretation(interpretation),
+ instance: instance_hash_for_interpretation(interpretation)
+ }
+ end
+
+ def result
+ @xml.root
+ end
+
+ def interpretation_nodes
+ result.xpath('interpretation').sort_by { |int| -int[:confidence].to_i }
+ end
+ end
+ end
+end
View
101 spec/ruby_speech/nlsml_spec.rb
@@ -1,9 +1,8 @@
require 'spec_helper'
describe RubySpeech::NLSML do
- describe 'drawing a document' do
- let :expected_document do
- string = '''
+ let :example_document do
+ '''
<result xmlns:myApp="foo" xmlns:xf="http://www.w3.org/2000/xforms" grammar="http://flight">
<interpretation confidence="60">
<input mode="speech">I want to go to Pittsburgh</input>
@@ -14,7 +13,7 @@
</xf:model>
<xf:instance>
<myApp:airline>
- <myApp:to_city>Pittsburgh</to_city>
+ <myApp:to_city>Pittsburgh</myApp:to_city>
</myApp:airline>
</xf:instance>
</interpretation>
@@ -27,13 +26,17 @@
</xf:model>
<xf:instance>
<myApp:airline>
- <myApp:to_city>Stockholm</to_city>
+ <myApp:to_city>Stockholm</myApp:to_city>
</myApp:airline>
</xf:instance>
</interpretation>
</result>
-'''
- Nokogiri::XML(string).to_xml
+ '''
+ end
+
+ describe 'drawing a document' do
+ let :expected_document do
+ Nokogiri::XML(example_document).to_xml
end
it "should allow building a document" do
@@ -74,4 +77,88 @@
document.to_xml.should == expected_document
end
end
+
+ describe "parsing a document" do
+ subject do
+ RubySpeech.parse example_document
+ end
+
+ its(:grammar) { should == 'http://flight' }
+
+ it { should be_match }
+
+ let(:expected_best_interpretation) do
+ {
+ confidence: 0.6,
+ input: { mode: :speech, content: 'I want to go to Pittsburgh' },
+ instance: { airline: { to_city: 'Pittsburgh' } }
+ }
+ end
+
+ let(:expected_interpretations) do
+ [
+ expected_best_interpretation,
+ {
+ confidence: 0.4,
+ input: { content: 'I want to go to Stockholm' },
+ instance: { airline: { to_city: 'Stockholm' } }
+ }
+ ]
+ end
+
+ its(:interpretations) { should == expected_interpretations }
+ its(:best_interpretation) { should == expected_best_interpretation }
+
+ context "without any interpretations" do
+ let :doc_without_interpretations do
+ '''
+<result xmlns:xf="http://www.w3.org/2000/xforms" grammar="http://flight"/>
+ '''
+ end
+
+ subject do
+ RubySpeech.parse doc_without_interpretations
+ end
+
+ it { should_not be_match }
+ end
+
+ context "with interpretations out of confidence order" do
+ let :example_document do
+ '''
+<result xmlns:myApp="foo" xmlns:xf="http://www.w3.org/2000/xforms" grammar="http://flight">
+ <interpretation confidence="40">
+ <input>I want to go to Stockholm</input>
+ <xf:model>
+ <xf:group name="airline">
+ <xf:string name="to_city"/>
+ </xf:group>
+ </xf:model>
+ <xf:instance>
+ <myApp:airline>
+ <myApp:to_city>Stockholm</myApp:to_city>
+ </myApp:airline>
+ </xf:instance>
+ </interpretation>
+ <interpretation confidence="60">
+ <input mode="speech">I want to go to Pittsburgh</input>
+ <xf:model>
+ <xf:group name="airline">
+ <xf:string name="to_city"/>
+ </xf:group>
+ </xf:model>
+ <xf:instance>
+ <myApp:airline>
+ <myApp:to_city>Pittsburgh</myApp:to_city>
+ </myApp:airline>
+ </xf:instance>
+ </interpretation>
+</result>
+ '''
+ end
+
+ its(:interpretations) { should == expected_interpretations }
+ its(:best_interpretation) { should == expected_best_interpretation }
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.