سؤال

أقوم بتطبيق مصدر لتنسيق بيانات XML يتطلب مساحات السمع. أنا أستخدم Builder Nokogiri XML (الإصدار 1.4.0) للقيام بذلك.

ومع ذلك، لا يمكنني الحصول على Nokogiri لإنشاء عقدة جذر مع مساحة اسم.

هذا يعمل:

Nokogiri::XML::Builder.new { |xml| xml.root('xmlns:foobar' => 'my-ns-url') }.to_xml

<?xml version="1.0"?>
<root xmlns:foobar="my-ns-url"/>

كما يفعل هذا:

Nokogiri::XML::Builder.new do |xml| 
  xml.root('xmlns:foobar' => 'my-ns-url') { xml['foobar'].child }
end.to_xml

<?xml version="1.0"?>
<root xmlns:foobar="my-ns-url">
  <foobar:child/>
</root>

ومع ذلك، أحتاج إلى شيء مثل <foo:root> وهذا لا يعمل:

Nokogiri::XML::Builder.new { |xml| xml['foobar'].root('xmlns:foobar' => 'my-ns-url') }.to_xml

NoMethodError: undefined method `namespace_definitions' for #<Nokogiri::XML::Document:0x11bfef8 name="document">

يجب تحديد مساحات الأسماء قبل الاستخدام، على ما يبدو، لذلك لا توجد طريقة لإضافة واحدة إلى عقدة الجذر.

وجدت سؤال حول هذا على القائمة البريدية Nokogiri, ، لكن ليس لديها ردود. أي شخص لديه حل؟

هل كانت مفيدة؟

المحلول

require 'rubygems'
require 'nokogiri'

puts Nokogiri::XML::Builder.new { |xml| 
  xml.root("xmlns:foo"=>"url") {
    xml.parent.namespace = xml.parent.namespace_definitions.find{|ns|ns.prefix=="foo"}
    xml['foo'].child
  }
}.to_xml

لا يمكنك استخدام xml['foo'] قبل تعريف مساحة الاسم، أي قبل تمريرها كوسيطة لعقدة الجذر. وبالتالي، فإن التعليمات البرمجية أعلاه تضيف مساحة الاسم بعد الحقيقة إلى عقدة الجذر.

نصائح أخرى

بعد عامين، وجدت طريقة نظافة للقيام بذلك باستخدام Nokogiri::XML::Builderمرجع المستند لاسترداد عقدة الجذر وإضافة مساحة الاسم (الأسماء) إلى ذلك. مثل الحل السابق، فإنه يتطلب العقدة الجذرية موجودة قبل أن تتم إضافة مساحات الأسماء إليها.

لقد غيرت <root> عنصر ل <rootElement> لذلك هذا هو أكثر واضحة:

builder = Nokogiri::XML::Builder.new do |xml| 
  xml.rootElement do
    # create a namespace and save it for later
    ns = xml.doc.root.add_namespace_definition('foo', 'my-ns-url')
    # you can also create multiple name spaces
    xml.doc.root.add_namespace_definition('bar', 'http://example.com/bar')

    # assign the saved namespace to rootElement
    xml.doc.root.namespace = ns

    xml['foo'].child
    xml['bar'].child
  end
end

حاليا، builder.to_xml سيعود:

<?xml version="1.0"?>
<foo:rootElement xmlns:foo="my-ns-url" xmlns:bar="http://example.com/bar">
  <foo:child/>
  <bar:child/>
</foo:rootElement>

أحب هذا أفضل لأنك لا تضطر إلى البحث عن مساحة الاسم، ومن الأسهل إضافة مساحات أسماء متعددة.

بعد ثلاث سنوات من إجابة Luke، أصبحت أبسط ذلك. يمكنك الآن استخدام مساحة الاسم "قبل" محددة. هذا الرمز:

require 'nokogiri'

NAMESPACES = { 'xmlns:foo' => 'bar', 'xmlns:baz' => 'bat' }

builder = Nokogiri::XML::Builder.new { |xml|
  xml['foo'].RootElement(NAMESPACES) {
    xml['baz'].FirstChild
  }
}

puts builder.to_xml

مخرجات هذا XML:

<?xml version="1.0"?>
<foo:RootElement xmlns:foo="bar" xmlns:baz="bat">
  <baz:FirstChild/>
</foo:RootElement>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top