[Groonga-commit] ranguba/groonga-client at fe10be1 [master] select: support XML output

Back to archive index

Kouhei Sutou null+****@clear*****
Wed Sep 27 11:40:40 JST 2017


Kouhei Sutou	2017-09-27 11:40:40 +0900 (Wed, 27 Sep 2017)

  New Revision: fe10be1e44fab03d6f12f607f48b6376bb7bb426
  https://github.com/ranguba/groonga-client/commit/fe10be1e44fab03d6f12f607f48b6376bb7bb426

  Message:
    select: support XML output

  Added files:
    test/response/test-select-xml.rb
  Modified files:
    lib/groonga/client/response/base.rb
    lib/groonga/client/response/select.rb
    test/response/helper.rb

  Modified: lib/groonga/client/response/base.rb (+3 -11)
===================================================================
--- lib/groonga/client/response/base.rb    2017-08-21 10:06:44 +0900 (fe1d7c4)
+++ lib/groonga/client/response/base.rb    2017-09-27 11:40:40 +0900 (d123778)
@@ -93,18 +93,10 @@ module Groonga
 
           private
           def parse_xml(response)
-            # FIXME: Use more fast XML parser
-            # Extract as a class
             document = REXML::Document.new(response)
-            root_element = document.root
-            if root_element.name == "RESULT"
-              result_element = root_element
-              header = parse_xml_header(result_element)
-              body = parse_xml_body(result_element.elements[1])
-            else
-              header = nil
-              body = parse_xml_body(root_element)
-            end
+            result_element = document.root
+            header = parse_xml_header(result_element)
+            body = parse_xml_body(result_element.elements[1])
             [header, body]
           end
 

  Modified: lib/groonga/client/response/select.rb (+78 -0)
===================================================================
--- lib/groonga/client/response/select.rb    2017-08-21 10:06:44 +0900 (af4a714)
+++ lib/groonga/client/response/select.rb    2017-09-27 11:40:40 +0900 (72b8e07)
@@ -24,6 +24,84 @@ module Groonga
       class Select < Base
         Response.register("select", self)
 
+        class << self
+          private
+          def parse_xml(response)
+            document = REXML::Document.new(response)
+            return super if document.root.name == "RESULT"
+
+            result_page = document.elements["SEGMENTS/SEGMENT/RESULTPAGE"]
+            result_set = result_page.elements["RESULTSET"]
+            n_hits, columns, records = parse_xml_result_set(result_set)
+
+            navigation_entry = result_page.elements["NAVIGATIONENTRY"]
+            drilldowns = parse_xml_navigation_entry(navigation_entry)
+
+            header = nil
+            body = [
+              [
+                [n_hits],
+                columns,
+                *records,
+              ],
+              *drilldowns,
+            ]
+            [header, body]
+          end
+
+          def parse_xml_result_set(result_set)
+            n_hits = Integer(result_set.attributes["NHITS"])
+
+            columns = []
+            records = []
+            result_set.each_element("HIT") do |hit|
+              if columns.empty?
+                hit.each_element("FIELD") do |field|
+                  name = field.attributes["NAME"]
+                  columns << [name, "ShortText"]
+                end
+              end
+              record = []
+              hit.each_element("FIELD") do |field|
+                record << field.text
+              end
+              records << record
+            end
+
+            [n_hits, columns, records]
+          end
+
+          def parse_xml_navigation_entry(navigation_entry)
+            return [] if navigation_entry.nil?
+
+            drilldowns = []
+            navigation_entry.each_element("NAVIGATIONELEMENTS") do |elements|
+              n_hits = Integer(elements.attributes["COUNT"])
+              columns = []
+              drilldown = []
+              elements.each_element("NAVIGATIONELEMENT") do |element|
+                if columns.empty?
+                  element.attributes.each do |name, value|
+                    columns << [name, "ShortText"]
+                  end
+                end
+
+                drilldown << element.attributes.collect do |_, value|
+                  value
+                end
+              end
+
+              drilldowns << [
+                [n_hits],
+                columns,
+                *drilldown,
+              ]
+            end
+
+            drilldowns
+          end
+        end
+
         include Enumerable
 
         # @return [Integer] The number of records that match againt

  Modified: test/response/helper.rb (+11 -2)
===================================================================
--- test/response/helper.rb    2017-08-21 10:06:44 +0900 (967fd0a)
+++ test/response/helper.rb    2017-09-27 11:40:40 +0900 (4116433)
@@ -16,9 +16,18 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 module TestResponseHelper
-  def parse_raw_response(command_name, raw_response)
+  def parse_raw_response_raw(command_name, pair_arguments, raw_response)
     command_class = Groonga::Command.find(command_name)
-    command = command_class.new(command_name, {})
+    command = command_class.new(command_name, pair_arguments)
     Groonga::Client::Response.parse(command, raw_response)
   end
+
+  def parse_raw_response(command_name, raw_response)
+    parse_raw_response_raw(command_name, {}, raw_response)
+  end
+
+  def parse_raw_xml_response(command_name, raw_response)
+    parse_raw_response_raw(command_name, {"output_type" => "xml"},
+                           raw_response)
+  end
 end

  Added: test/response/test-select-xml.rb (+105 -0) 100644
===================================================================
--- /dev/null
+++ test/response/test-select-xml.rb    2017-09-27 11:40:40 +0900 (d656aa5)
@@ -0,0 +1,105 @@
+# Copyright (C) 2017  Kouhei Sutou <kou �� clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+require "response/helper"
+
+class TestResponseSelectXML < Test::Unit::TestCase
+  include TestResponseHelper
+
+  def drilldown(key, n_hits, records)
+    Groonga::Client::Response::Select::Drilldown.new(key, n_hits, records)
+  end
+
+  def test_basic
+    raw_response = <<-XML
+<?xml version="1.0" encoding="utf-8"?>
+<SEGMENTS>
+<SEGMENT>
+<RESULTPAGE>
+<RESULTSET OFFSET="0" LIMIT="1" NHITS="100">
+<HIT NO="1">
+<FIELD NAME="_id">1</FIELD>
+</HIT>
+</RESULTSET>
+</RESULTPAGE>
+</SEGMENT>
+</SEGMENTS>
+    XML
+
+    response = parse_raw_xml_response("select", raw_response)
+    assert_equal({
+                   :return_code => 0,
+                   :start_time => Time.at(0),
+                   :elapsed_time => 0.0,
+                   :records => [{"_id" => "1"}],
+                 },
+                 {
+                   :return_code => response.return_code,
+                   :start_time => response.start_time,
+                   :elapsed_time => response.elapsed_time,
+                   :records => response.records,
+                 })
+  end
+
+  def test_drilldown
+    raw_response = <<-XML
+<?xml version="1.0" encoding="utf-8"?>
+<SEGMENTS>
+<SEGMENT>
+<RESULTPAGE>
+<RESULTSET OFFSET="0" LIMIT="0" NHITS="100">
+</RESULTSET>
+<NAVIGATIONENTRY>
+<NAVIGATIONELEMENTS COUNT="7">
+<NAVIGATIONELEMENT _key="2.2.0" _nsubrecs="18044" />
+<NAVIGATIONELEMENT _key="2.3.0" _nsubrecs="18115" />
+<NAVIGATIONELEMENT _key="2.4.0" _nsubrecs="14594" />
+</NAVIGATIONELEMENTS>
+</NAVIGATIONENTRY>
+</RESULTPAGE>
+</SEGMENT>
+</SEGMENTS>
+    XML
+
+    response = parse_raw_response_raw("select",
+                                      {
+                                        "drilldown" => "version",
+                                        "output_type" => "xml",
+                                      },
+                                      raw_response)
+    drilldown_records = [
+      {"_key" => "2.2.0", "_nsubrecs" => "18044"},
+      {"_key" => "2.3.0", "_nsubrecs" => "18115"},
+      {"_key" => "2.4.0", "_nsubrecs" => "14594"},
+    ]
+    assert_equal({
+                   :return_code => 0,
+                   :start_time => Time.at(0),
+                   :elapsed_time => 0.0,
+                   :records => [],
+                   :drilldowns => [
+                     drilldown("version", 7, drilldown_records),
+                   ],
+                 },
+                 {
+                   :return_code => response.return_code,
+                   :start_time => response.start_time,
+                   :elapsed_time => response.elapsed_time,
+                   :records => response.records,
+                   :drilldowns => response.drilldowns,
+                 })
+  end
+end
-------------- next part --------------
HTML����������������������������...
URL: https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20170927/d6c70de3/attachment-0001.htm 



More information about the Groonga-commit mailing list
Back to archive index