Search code examples
rubyxmlxml-simple

How to use XmlSimple to produce an XML element with attribute and text node?


I have a problem that sounds basic, but I haven't found a solution anywhere. I'm using the Ruby version of XmlSimple, specifically the xml_out function.

The Problem

I'm having trouble outputting an element which would have one attribute node and a text node. Here's what I want:

<lane id='1'>unchannelized</lane>

Here's what I currently get:

<lane id='1'>
  <content>unchannelized</content>
</lane>

I've tried to use the "ContentKey" => 'content' option to xml_out (in addition to the "AttrPrefix" => true), but that yielded the same result. I've tried to change the ContentKey as well, same difference.

Relevant Code

The attribute & text node getting added to an array:

laneConfigArr << {"@id" => laneNo,  "content" => netsimLaneChannelizationCode(matchArr[matchIndex])}

The actual hash being generated:

unhappyHash << {
   #more stuff here,
   "LaneConfig" => {"lane" => laneConfigArr},
   #more stuff here
}

The xml_out call [EDITED]:

result["NetsimLinks"] = {"NetsimLink" => unhappyHash}
doc = XmlSimple.xml_out(result, {"AttrPrefix" => true, "RootName" => "CORSIMNetwork", "ContentKey" => "content"})

Environment Details

  • OS: Windows 7
  • Ruby: 1.9.3-p125
  • XmlSimple: 1.0.13

Looked everywhere, no-one seems to have had this problem. Perhaps I'm missing something, or maybe this cannot/shouldn't be done?

I'd highly appreciate any help with this.


Solution

  • The nice thing about XmlSimple is that it is round-trippable: that is, you can put your desired output through xml_in and it will give you what you need to produce it with xml_out.

    So let's take a look. Say we have the following simplified XML:

    require 'xmlsimple'
    
    xml = %Q(
      <CORSIMNetwork>
        <lane id='1'>unchannelized</lane>
      </CORSIMNetwork>
    )
    

    Now let's see what we get as a result of XmlSimple.xml_in(xml):

    {"lane"=>[{"id"=>"1", "content"=>"unchannelized"}]}
    

    The root is gone, because we haven't specified the KeepRoot option, but otherwise it is what we expect.

    Now let's do an xml_out on it specifying the RootName option to get the root back:

    <CORSIMNetwork>
      <lane id="1">unchannelized</lane>
    </CORSIMNetwork>
    

    Looks OK. I checked the AttrPrefix option, and other than requiring "@id" instead of "id" key in the input, the output is still the same.

    Full script that produces correct output:

    require 'xmlsimple'
    
    lane_config = [{ "@id" => 1, "content" => "unchannelized"}]
    unhappy = {
       "LaneConfig" => {"lane" => lane_config},
    }
    
    doc = XmlSimple.xml_out(unhappy, {"AttrPrefix" => true, 
                                      "RootName"   => "CORSIMNetwork",
                                      "ContentKey" => "content"
                     })
    puts doc
    

    Output:

    <CORSIMNetwork>
      <LaneConfig>
        <lane id="1">unchannelized</lane>
      </LaneConfig>
    </CORSIMNetwork>
    

    Since the above works for me, the only thing I can think of is that your hash must not contain what you think it contains.