views:

39

answers:

1

I am trying the following, but the output XML is badly formed:

 xml = Builder::XmlMarkup.new({:target => display })

xml.instruct!

xml.mail {  
  xml.documents {
    xml.document {
      xml.template {
        xml.source "gallery"
        xml.name "Postcard: Image fill front"
      }
      xml.sections {
        xml.section {
          xml.name "Text"
          xml.text "Hello, world"
        }

        xml.section {
           xml.name "Image"
           xml.attachment "1136946686-3425"
        }
      } #sections
    } #document         
  } #documents

  xml.addresses {
    xml.addressee {
      xml.name "Me"
      xml.address "Street"
      xml.city "San Francisco"
      xml.state "CA"
    }
  }  
}    
@xml_display = xml

I need it to look more like this:

<?xml version="1.0" encoding="UTF-8"?>
<mail>
  <documents>
    <document>
      <template>
        <source>gallery</source>
        <name>Postcard: Image fill front</name>
      </template>
      <sections>
         <section>
           <name>Text</name>
           <text>Hello, World!</text>
          </section>
       <section>
          <name>Image</name>
          <attachment>...attachment id...</attachment>
          </section>
       </sections>
    </document>
  </documents>
  <addressees>
    <addressee>
      <name>John Doe</name>
      <address>123 Main St</address>
      <city>Anytown</city>
      <state>AZ</state>
      <postal-code>10000</postal-code>
    </addressee>
  </addressees>
</mail>

My code ends up looking like this in the view (page source):

<?xml version="1.0" encoding="UTF-8"?><mail/><documents/><document/><template/><source>gallery</source><name>Postcard:  Image fill front</name>

NOTE: The final XML needs to be POSTED to a URL, and I am using rest-client and so want everything to become an instance variable that is passed as the body.

The instance variable is just @xml_display = xml but it's not working... :(

A: 

You can pass a block to each of those to nest the items.

xml.mail do |mail|
  mail.documents do |documents|
    documents.document do |document|
      document.template do |template|
        template.source "gallery"
        template.name "Postcard:  Image fill front"
      end
    end
  end
end

There's more information on the builder rubyforge page.

theIV
Hi, thanks, yeah, I checked it out...it suggested that I could nest { } as well and made the changes...still getting a 422 error ... perhaps I need to define a target rather than assigning xml to an @instance?
Angela
Looking at your updated question, you still need to pass a variable to your block and then use that variable for the next element. Notice in my example the `|mail|` and how I then use `mail.documents`.
theIV
I see, let me try that, how do I send the entire xml into an object? I tried using {:target => @target} but it doesn't display anything
Angela
or is it @display = xml?
Angela
Are you doing this in a controller or in a view? If you are doing it in a view, if you have your `respond_to` block set up to accept xml, then whenever someone hits that action and wants xml, it will use your xml template. Is this not what you are trying to do?
theIV
I'm doing it in the controller....I need to pass it into a SOAP call....
Angela
Have you tried this with Nokogiri, i am using that now....
Angela
Can you build xml with Nokogiri? As far as I knew, it was only a parser.
theIV
thanks, I ended up using the builder for another part and this worked, although Nokogiri is pretty cool as a builder.
Angela