ActiveRecord对象的XML序列化(to_xml)的默认行为将发出类似于XML Schema Instance属性的“type”和“nil”属性,但不在XML命名空间中设置。
例如,模型可能会生成如下输出:
<user>
<username nil="true" />
<first-name type="string">Name</first-name>
</user>
有没有让to_xml利用XML Schema Instance命名空间并为属性和值添加前缀?
使用上面的例子,我想产生以下内容:
<user xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xs="http://www.w3.org/1999/XMLSchema">
<username xsi:nil="true" />
<first-name xsi:type="xs:string">Name</first-name>
</user>
答案 0 :(得分:2)
我有类似的要求,并选择了子类:: Builder :: XmlMarkup:
require 'builder/xmlmarkup'
class MyXmlMarkup < ::Builder::XmlMarkup
def tag!(sym, *args, &block)
if @level == 0 # Root element
args << {"xmlns" => "http://my_company.com/api/schemas/xml",
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"}
end
if args[:nil] = true
args << {"xsi:nil" => true}
end
super(sym, *args, &block)
end
end
然后你可以用它:
foo.to_xml(builder: MyXmlMarkup.new(indent: 2))
答案 1 :(得分:1)
我碰到了类似的东西,但在Hash上调用#to_xml时,而不是在AR实例上调用#to_xml。
我想出了这个帮手:
#
# Returns a new Builder::XmlMarkup that'll handle API's to_xml needs
# Usually you don't need to construct a builder, as to_xml will create one
# however we need some things modified (adding a namespace, XSD-nillable-compliant-nils
# and to_xml is too braindead to allow us to alter such behaviors externally
#
def api_new_xml_builder
builder = Builder::XmlMarkup.new(:indent => 2)
class << builder
def method_missing(*args, &block)
@api_seen ||= 0
@api_seen += 1
if @api_seen == 1
# Root element. Needs some decoration
args[1] ||= {}
args[1]["xmlns"] = "http://my_company.com/api/schemas/xml"
args[1]["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
end
if args[2].is_a?(Hash) && args[2][:nil] == true
args[2]["xsi:nil"] = true
end
super(*args, &block)
end
end
builder
end
然后像这样使用:
builder = api_new_xml_builder
foo.to_xml(:builder => builder)
请注意,我选择保留现有的nil =和type =属性,并添加我自己的xsi-prefixed nil,但是替换它们是微不足道的。