ohho
ohho

Reputation: 51951

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:

Upvotes: 1

Views: 215

Answers (2)

matt
matt

Reputation: 79813

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>

Upvotes: 1

ohho
ohho

Reputation: 51951

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>

Upvotes: 0

Related Questions