ruby एक्सएमएल टू हैश रूपांतरण: नोरी गहरे एक्सएमएल तत्वों के गुणों को छोड़ देता है



xml hash (1)

नोरि वास्तव में विशेषताओं को छोड़ नहीं रहा है, वे सिर्फ मुद्रित नहीं किए जा रहे हैं।

यदि आप रूबी स्क्रिप्ट चलाते हैं:

require 'nori'

data = Nori.new(empty_tag_value: true).parse(<<XML)
<?xml version="1.0"?>
<root>
  <objects>
    <object>
      <fields>
        <field name="Name">The name</field>
        <field name="Description">A description</field>
      </fields>
    </object>
  </objects>
</root>
XML

field_list = data['root']['objects']['object']['fields']['field']

puts "text: '#{field_list[0]}' data: #{field_list[0].attributes}"
puts "text: '#{field_list[1]}' data: #{field_list[1].attributes}"

आपको आउटपुट प्राप्त करना चाहिए

["The name", "A description"]
text: 'The name' data: {"name"=>"Name"}
text: 'A description' data: {"name"=>"Description"}

जो स्पष्ट रूप से दिखाता है कि विशेषता वहां है, लेकिन inspect विधि द्वारा प्रदर्शित नहीं की जाती है ( p(x) फ़ंक्शन puts x.inspect के समान puts x.inspect )।

आप देखेंगे कि puts field_list.inspect आउटपुट ["The name", "A description"] puts field_list.inspect । लेकिन field_list[0].attributes । सामग्री गुण कुंजी और डेटा मुद्रित करता है।

यदि आप pp डिस्प्ले करना चाहते हैं तो आप Nori::StringWithAttributes में inspect विधि को अधिभारित कर सकते हैं।

class Nori
  class StringWithAttributes < String
    def inspect
      [attributes, String.new(self)].inspect
    end
  end
end

या यदि आप आउटपुट को बदलना चाहते हैं तो आप एक अलग डेटा स्ट्रक्चर वापस करने के लिए self.new विधि को self.new कर सकते हैं।

class Nori
  class MyText < Array
    def attributes=(data)
      self[1] = data
    end
    attr_accessor :text
    def initialize(text)
      self[0] = text
      self[1] = {}
    end
  end
  class StringWithAttributes < String
    def self.new(x)
      MyText.new(x)
    end
  end
end

और डेटा को टुपल के रूप में एक्सेस करें

puts "text: '#{data['root']['objects']['object']['fields']['field'][0].first}' data: #{ data['root']['objects']['object']['fields']['field'][0].last}"

यह ऐसा करेगा ताकि आपके पास जेएसओएन या वाईएएमएल के रूप में डेटा हो सके क्योंकि टेक्स्ट आइटम 2 तत्वों के साथ सरणी की तरह दिखेंगे। pp भी काम करता है।

{"root"=>
  {"objects"=>
    {"object"=>
      {"fields"=>
        {"field"=>
          [["The name", {"name"=>"Name"}],
           ["A description", {"name"=>"Description"}]]},
       "bob"=>[{"@id"=>"id1"}, {"@id"=>"id2"}],
       "bill"=>
        [{"p"=>["one", {}], "@id"=>"bid1"}, {"p"=>["two", {}], "@id"=>"bid2"}],
       "@id"=>"1"}}}}

यह वही करना चाहिए जो आप चाहते हैं।

require 'awesome_print'
require 'nori'

# Copyright (c) 2016 G. Allen Morris III
#
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
module AwesomePrint
  module Nori

    def self.included(base)
      base.send :alias_method, :cast_without_nori, :cast
      base.send :alias_method, :cast, :cast_with_nori
    end

    # Add Nori XML Node and NodeSet names to the dispatcher pipeline.
    #-------------------------------------------------------------------
    def cast_with_nori(object, type)
      cast = cast_without_nori(object, type)
      if defined?(::Nori::StringWithAttributes) && object.is_a?(::Nori::StringWithAttributes)
        cast = :nori_xml_node
      end
      cast
    end

    #-------------------------------------------------------------------
    def awesome_nori_xml_node(object)
      return %Q|["#{object}", #{object.attributes}]|
    end
  end
end

AwesomePrint::Formatter.send(:include, AwesomePrint::Nori)

data = Nori.new(empty_tag_value: true).parse(<<XML)
<?xml version="1.0"?>
<root>
  <objects>
    <object>
      <fields>
        <field name="Name">The name</field>
        <field name="Description">A description</field>
      </fields>
    </object>
  </objects>
</root>
XML

ap data

आउटपुट के रूप में है:

{
    "root" => {
        "objects" => {
            "object" => {
                "fields" => {
                    "field" => [
                        [0] ["The name", {"name"=>"Name"}],
                        [1] ["A description", {"name"=>"Description"}]
                    ]
                }
            }
        }
    }
}

सारांश

मैं अपनी मशीन पर रुबी ( ruby 2.1.2p95 (2014-05-08) [x86_64-linux-gnu] का उपयोग कर रहा हूं, उत्पादन वातावरण में ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux] ) और नोरि एक रूबी हैश में एक एक्सएमएल दस्तावेज (प्रारंभ में नोकोगिरी के साथ संसाधित) को परिवर्तित करने के लिए, लेकिन बाद में मुझे पता चला कि नोरी गहरे एक्सएमएल तत्वों के गुणों को छोड़ रहा है।

अंक विवरण और पुनरुत्पादन

ऐसा करने के लिए, मैं निम्नलिखित के समान कोड का उपयोग कर रहा हूं:

xml  = Nokogiri::XML(File.open('file.xml')) { |config| config.strict.noblanks }
hash = Nori.new.parse xml.to_s

कोड आम तौर पर एक मामले को छोड़कर, इरादे के रूप में काम करता है। जब भी नोरी एक्सएमएल पाठ को पारदर्शी करता है, तो यह पत्ती तत्वों से तत्व विशेषताओं को छोड़ देता है (यानी तत्व जिनके पास कोई बाल तत्व नहीं है)।

उदाहरण के लिए, निम्न दस्तावेज़:

<?xml version="1.0"?>
<root>
  <objects>
    <object>
      <fields>
        <id>1</id>
        <name>The name</name>
        <description>A description</description>
      </fields>
    </object>
  </objects>
</root>

... अपेक्षित हैश में परिवर्तित हो गया है (ब्रेवटी के लिए छोड़ा गया कुछ आउटपुट):

irb(main):066:0> xml = Nokogiri::XML(txt) { |config| config.strict.noblanks }
irb(main):071:0> ap Nori.new.parse(xml.to_s), :indent => -2
{
  "root" => {
    "objects" => {
      "object" => {
        "fields" => {
          "id"   => "1",
          "name" => "The name"
          "description" => "A description"
        }
      }
    }
  }
}

समस्या तब दिखाई देती है जब कोई तत्व वाले तत्वों पर तत्व विशेषताओं का उपयोग नहीं किया जाता है। उदाहरण के लिए, निम्न दस्तावेज़ अपेक्षित रूपांतरित नहीं किया गया है:

<?xml version="1.0"?>
<root>
  <objects>
    <object id="1">
      <fields>
        <field name="Name">The name</field>
        <field name="Description">A description</field>
      </fields>
    </object>
  </objects>
</root>

वही Nori.new.parse(xml.to_s) , जैसा कि Nori.new.parse(xml.to_s) द्वारा प्रदर्शित किया गया है, दिखाता है कि गहरे <field> तत्व अनुपस्थित हैं :

irb(main):131:0> ap Nori.new.parse(xml.to_s), :indent => -2
{
  "root" => {
    "objects" => {
      "object" => {
        "fields" => {
          "field" => [
            [0] "The name",
            [1] "A description"
          ]
        },
        "@id"    => "1"
      }
    }
  }
}

हैश के पास केवल उनके मूल्य एक सूची के रूप में हैं, जो मैं नहीं चाहता था। मुझे <field> तत्वों को उनके गुणों को अपने मूल तत्वों की तरह बनाए रखने की उम्मीद है (उदाहरण के लिए <object> @id="1" <object> ), उनके गुणों को कटा हुआ नहीं होने के लिए।

भले ही दस्तावेज़ को निम्नानुसार देखने के लिए संशोधित किया गया हो, फिर भी यह अपेक्षित के रूप में काम नहीं करता है:

<?xml version="1.0"?>
<root>
  <objects>
    <object id="1">
      <fields>
        <Name type="string">The name</Name>
        <Description type="string">A description</Description>
      </fields>
    </object>
  </objects>
</root>

यह निम्नलिखित हैश का उत्पादन करता है:

{
  "root" => {
    "objects" => {
      "object" => {
        "fields" => {
          "Name"        => "The name",
          "Description" => "A description"
        },
        "@id"    => "1"
      }
    }
  }
}

जिसमें प्रत्येक फ़ील्ड एंट्री के लिए type="whatever" विशेषताएं हैं।

आखिरकार आखिरी पोस्ट (अगस्त 2015 से) के साथ मुझे समस्या # 59 पर ले जाने का कहना है कि वह "नोरी के कोड में बग नहीं ढूंढ सकता"।

निष्कर्ष

तो, मेरा सवाल यह है: क्या आप में से कोई भी नोरी मुद्दे (उदाहरण के लिए शायद एक सेटिंग) के आसपास काम करने के तरीके से अवगत है, जो मुझे मेरी मूल स्कीमा (यानी बच्चों के साथ तत्वों में विशेषताओं के साथ) का उपयोग करने की अनुमति देगा? यदि हां, तो क्या आप एक कोड स्निपेट साझा कर सकते हैं जो इसे सही तरीके से संभाल लेंगे?

मुझे अपनी एक्सएमएल स्कीमा को दोबारा डिजाइन करना था और इसे काम करने के लिए लगभग तीन बार कोड बदलना था, इसलिए अगर नोरी को व्यवहार करने का कोई तरीका है, और मुझे बस इसके बारे में पता नहीं है, तो मैं जानना चाहता हूं कि यह क्या है है।

मैं जितना संभव हो उतना पुस्तकालयों को स्थापित करने से बचाना चाहता हूं, जो कि मैं मूल रूप से उपयोग करना चाहता था, स्कीमा संरचना के साथ ठीक से काम करने के लिए, लेकिन अगर यह काम साबित हुआ तो मैं संभावना के लिए खुला हूं। (मुझे कोड को दोबारा फिर से कारक करना होगा ...) फ्रेमवर्क निश्चित रूप से इसके लिए अधिक हैं, इसलिए कृपया: रूबी या इसी तरह के पूर्ण-स्टैक समाधान पर रुबी का सुझाव न दें

कृपया ध्यान दें कि मेरा वर्तमान समाधान, (अनिच्छा से) पुन: डिज़ाइन किए गए स्कीमा के आधार पर काम कर रहा है, लेकिन मूल की तुलना में उत्पन्न और प्रक्रिया करना अधिक जटिल है, और मैं वापस सरल / उथल-पुथल स्कीमा पर जाना चाहता हूं।





hash