簡體   English   中英

用REXML編寫命名空間的XML

[英]Writing namespaced XML with REXML

我正在使用涉及多個名稱空間的XML(特別是ResourceSync ,它在Sitemap文檔中嵌入了名稱空間的標記)。

創建REXML元素時,可以設置全局名稱空間:

foo = REXML::Element.new('foo')
foo.add_namespace('http://foo.com/')

puts foo # outputs <foo xmlns='http://foo.com/'/>

我可以創建一個帶有前綴的名稱空間:

foo.add_namespace('bar', 'http://bar.org/')

puts foo # outputs <foo xmlns:bar='http://bar.org/' xmlns='http://foo.com/'/>

但是,如果我隨后添加了另一個與前綴具有相同名稱空間URI的元素,但未明確使用前綴-

bar = REXML::Element.new('bar')
bar.add_namespace('http://bar.org/')
foo.add_element(bar)

-REXML不夠聰明,無法注意到前綴的存在並使用它。 而不是預期的

<foo xmlns:bar='http://bar.org/' xmlns='http://foo.com/'>
  <bar:bar/>
</foo>

我得到了不必要的冗長:

<foo xmlns:bar='http://bar.org/' xmlns='http://foo.com/'>
  <bar xmlns='http://bar.org/'/>
</foo>

我可以通過完全忽略名稱空間URI並僅將前綴修改為元素名稱來解決此問題:

baz = REXML::Element.new('bar:baz')
foo.add_element(baz)

但是,在創建元素時,我唯一可以確定的就是名稱空間URI -我不知道它將添加到哪個父元素或那里可能存在什么名稱空間前綴。 (而且名稱空間前綴實際上並不是邏輯文檔模型的一部分,而名稱空間URI確實是。)

有沒有辦法讓REXML在輸出時解析前綴,和/或有一種直接的方法來對REXML文檔進行后處理以使用前綴?

請注意,我並不是要尋找Nokogiri解決方案,因為我使用的是庫,即內部使用REXML的xml映射 (碰巧,它似乎也沒有任何名稱空間的概念,但是我已經找到解決該問題的方法)。

試試這個代碼:

require 'rexml/document'

foo = REXML::Element.new('foo')
foo.add_namespace('http://foo.com/')
foo.add_namespace('bar', 'http://bar.org/')

bar = REXML::Element.new('bar')
bar.add_namespace('http://bar.org/')
foo.add_element(bar)

def normalize_namespace!(elem)
  if elem.attributes['xmlns']
    prefix = elem.namespaces.reject { |key, _| key == 'xmlns' }.key(elem.namespace)
    elem.name = "#{prefix}:#{elem.name}"
    elem.delete_namespace
  end
end

foo.root.each_element_with_attribute('xmlns') { |e| normalize_namespace!(e) }

puts foo
# => <foo xmlns:bar='http://bar.org/' xmlns='http://foo.com/'><bar:bar/></foo>

解釋如下:

  1. each_element_with_attribute遍歷所有具有屬性xmlns xml節點。
  2. namespaces返回一個包含該節點所有名稱空間(包括其祖先)的哈希,例如,對於bar ,它將為: {"xmlns"=>"http://foo.com/", "bar"=>"http://bar.org/"}
  3. namespace空間通過檢查其屬性和祖先,返回最適合該節點的名稱空間。 對於bar它返回http://bar.org/
  4. name=訪問者同時分配一個簡短的名稱和一個擴展的名稱(如果存在,最后一個將用於渲染)
  5. 最后, delete_namespace刪除多余xmlns='http://bar.org/'bar

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM