SitePoint Sponsor

User Tag List

Results 1 to 8 of 8

Thread: building xml

Hybrid View

  1. #1
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    building xml

    I'm having trouble trying to build up an xml file.

    basically I'm looping thru an array and I want to append items to a node based on a value.

    so if i have an array like:

    PHP Code:
     my_array = [["sam""string 1"], ["sam""string 2"], ["joe""string 1"]] 
    I want to end up with xml like:

    <people>
    <person ="sam">
    <dialog>string 1</dialog>
    <dialog>string 2</dialog>
    </person>
    <person ="joe">
    <dialog>string 1</dialog>
    </person>
    </people>

    Here's my attempt:
    PHP Code:
      people_listing_xml ="<people>\n"
      
    people_xml Builder::XmlMarkup.new(:target => people_listing_xml, :indent => 1)
      
      
    //inside the loop
              
    people_xml.chat "person"=>person do
                  
    people_xml.dialog dialog
              end
      
      people_listing_xml 
    << "</people>\n" 
    thanks for any help

  2. #2
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I guess my question really is how do I append values to any existing node?

    So, in my example if I wanted to add some more entries for "sam" I would need to select the person with the id of sam and add an entry.
    I know this is probably simple stuff but I'm stumped

  3. #3
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think this function is helpful:

    Code:
    people = [["sam", "a"], ["sam", "b"], ["joe", "c"]] 
    
    def group(ary)
      res = {}
      for ele in ary
        res[ele[0]] = (res[ele[0]] || []) + [ele[1]]
      end and res
    end
    
    group(people) # => {"joe"=>["c"], "sam"=>["a", "b"]}

  4. #4
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey Fenrir, thanks for that.
    I'm not sure how it applies to my problem though.
    Is it really as hard as I think it is to append to an xml node?

  5. #5
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes. I don't know how builder works exactly, but it seems to be nearly impossible to append to an existing node.

    That's why I wrote that function ;-). If you look closely, you see that the function transforms the original array to a hash that's structured like your XML. You should insert a new loop *inside* people_xml.chat "person"=>person do ... end, and add a node for every element in the array of the hash.

    Please tell me if this isn't clear.

  6. #6
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,
    Yes, your method is clear. Just suprised you can not simply append to a node
    Thanks

  7. #7
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually it's not strange at all, because builder doesn't create an object model of the xml, but it just creates a string. If you want to append to a node, use REXML, but in your case, this is an overkill.

    Also:

    Code:
     people_listing_xml ="<people>\n"
      people_xml = Builder::XmlMarkup.new(:target => people_listing_xml, :indent => 1)
      
      //inside the loop
              people_xml.chat "person"=>person do
                  people_xml.dialog dialog
              end
      
      people_listing_xml << "</people>\n"
    Can be written like:

    Code:
    x = Builder::XmlMarkup.new(:indent => 1)
    x.people {
      //inside the loop
      x.chat(:person => person) {
        x.dialog dialog
      }
    }
    Which looks cleaner.

  8. #8
    SitePoint Member
    Join Date
    May 2005
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    require 'builder'
    
    my_array = [["sam", "string 1"], ["sam", "string 2"], ["joe", "string 1"]]
    my_hash = my_array.inject(Hash.new { [] }) { |g,p| g[p[0]] <<= p[1]; g }
    xml = Builder::XmlMarkup.new(:target => (my_output = ''), :indent => 1)
    xml.people do
      my_hash.each do |name, dialogs|
        xml.person :name => name do
          dialogs.each do |dialog| xml.dialog dialog end
        end
      end
    end
    
    print my_output
    Outputs this;
    Code:
    <people>
     <person name="joe">
      <dialog>string 1</dialog>
     </person>
     <person name="sam">
      <dialog>string 1</dialog>
      <dialog>string 2</dialog>
     </person>
    </people>
    Don't know if I really understood the problem, but at least it looks like what you wanted to end up with, so I hope it helped somewhat.
    I suppose if you wanted to add a new node you could just:
    my_array << ["sam", "some more"]
    and generate the xml again.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •