简体   繁体   中英

Generate XML with same attribute and element name by xml-simple

A vendor takes an XML with the following format:

<message type="login", serial="1"> 
  <site>BETA</site>
  <type>DEFAULT</type> 
  <username>john</username> 
  <password>1234</password>
</message>

Note: type is used in both attribute and element.

When I try to generate the XML by xml_simple :

data_2 = {'type' => 'login', 'serial' => 1, 
  'site' => ['content' => 'BETA'],
  'type' => ['content' => 'DEFAULT'],
  'username' => ['content' => 'john'],
  'password' => ['content' => '1234'],
}

xml_2 = XmlSimple.xml_out(data_2, {:rootname => 'message'})
puts xml_2

gives:

<message serial="1">
  <type>DEFAULT</type>
  <site>BETA</site>
  <username>john</username>
  <password>1234</password>
</message>

How to preserve type in both attribute and element of message :

The problem is you want both an attribute and a child element named type , so you hash has two keys with this name. Since keys in a hash are unique, the second key replaces the first, so the hash you actually pass to XmlSimple is:

data_2 = {'serial' => 1, 'site' => ['content' => 'BETA'], 'type' => ['content' => 'DEFAULT'], 'username' => ['content' => 'john'], 'password' => ['content' => '1234'], }

with the 'type' => 'login' entry replaced by 'type' => ['content' => 'DEFAULT'] .

One way around this using XmlSimple would be to use the AttrPrefix option, and prefix your attibute names with @ , (see the docs ):

data_2 = {'@type' => 'login', '@serial' => 1, 
  'site' => ['content' => 'BETA'],
  'type' => ['content' => 'DEFAULT'],
  'username' => ['content' => 'john'],
  'password' => ['content' => '1234'],
}

xml_2 = XmlSimple.xml_out(data_2, {:rootname => 'message', 'AttrPrefix' => true})
puts xml_2

Output:

<message type="login" serial="1">
  <site>BETA</site>
  <type>DEFAULT</type>
  <username>john</username>
  <password>1234</password>
</message>

I ended up using builder :

require 'builder'

username = 'john'
password = '1234'

xml = Builder::XmlMarkup.new(:indent => 2, :target => $stdout)
xml.message("type" => "login", "serial" => 1) {
  xml.site "BETA"
  xml.type "DEFAULT"
  xml.username username
  xml.password password
}

gives:

<message type="login" serial="1">
  <site>BETA</site>
  <type>DEFAULT</type>
  <username>john</username>
  <password>1234</password>
</message>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM