1

I am looking to refine functioning code. I am attempting to parse XML using the DOM and then display it on a visualforce page. Right now I am parsing each node into 3 lists of strings then calling the lists in visualforce. Displaying them side by side using a panel grid.

It would be ideal to create a class and use an instance of it to get each object and add it to a list of that type. Call the list in my visualforce page and use columns and the dot notation to access the different fields.

What are your thoughts?

This is a sample of what I am trying to parse. . . .

<response>
  <monthlyReport>
    <dailyRate>5</dailyRate>
    <weeklyRate>7</weeklyRate>
    <when>
      <year>2014</year>
      <month>8</month>
    </when>
  </monthlyReport>
  <monthlyReport>
    <dailyRate>3</dailyRate>
    <weeklyRate>8</weeklyRate>
    <when>
      <year>2014</year>
      <month>9</month>
    </when>
  </monthlyReport>
  <monthlyReport>
    <dailyRate>7</dailyRate>
    <weeklyRate>2</weeklyRate>
    <when>
      <year>2014</year>
      <month>10</month>
    </when>
  </monthlyReport>

This is how I'm currently parsing. . . . . .

public class ParseUtility{
    Transient public list<string> Month;
    Transient public list<string> year;
    Transient public list<decimal> weeklyRate;

    public list<string> parseRates(string toparse){
      month = new list<string>();
      weeklyRate = new list<decimal>();
      year = new list<string>();

      DOM.Document doc = new DOM.Document();
      doc.load(toParse);    
      DOM.XMLNode root = doc.getRootElement();

    return  walkthroughRates(root);
    }

    private list<string> walkThroughRates(dom.XMLNode node) {
        for (Dom.XMLNode child: node.getChildElements()) {
            walkThroughRates(child); 

            if(child.getName() == 'month'){
              month.add(child.gettext().trim());
            }
            if(child.getName() == 'weeklyRate'){
                weeklyRate.add(decimal.valueof(child.getText().trim()));
            }
            if(child.getName() == 'year'){
                year.add(child.getText().trim());
            }
        }
        return month;
    }

This is what I'm going for but I don't know how to do it with XML and the DOM

JSONparser parser = JSON.createparser(Results);
        while (parser.nextToken() != null) {
            if (parser.getCurrentToken() == JSONToken.START_ARRAY){
                while(parser.nextToken() != null){
                    if(parser.getCurrentToken() == JSONToken.START_OBJECT){
                        storages sto = (storages)parser.readvalueas(storages.class);
                        storagelist.add(sto);
                        system.debug('*****Serialized storage: ' + storagelist);
                    }
                }
            }
        }

        public class geometry{
            public Location location{get;set;}

            public geometry(Location location){
                this.location = location;
            }
        }
        public class Location{
            public decimal lat{get;set;}
            public decimal lng{get;set;}

            public Location(decimal lat, decimal lng){
                this.lat = lat;
                this.lng = lng;
            }
        }

    public class storages{
        public Geometry geometry{get;set;}
        public string id {get;set;}
        public string lat {get;set;}
        public string lng {get;set;}
        public string name {get;set;}
        public string vicinity {get;set;}
        public string place_id {get;set;}

        public storages(Geometry geometry, string recordid, string lt, string lg, string nm, string address, string place){
            id = recordid;
            lat = lt;
            lng = lg;
            name = nm;
            vicinity = address;
            place_id = place;
            this.geometry = geometry;
        }
    }  
1

Here is one way to do it (that may contain typos and errors as I haven't tested it):

public class Parser {

    public class MonthlyReport {
        public String month {get; set;}
        public String year {get; set;}
        public Decimal weeklyRate {get; set;}
    }

    public List<MonthlyReport> parse(string toParse) {
        List<MonthlyReport> reports = new List<MonthlyReport>();
        DOM.Document doc = new DOM.Document();
        doc.load(toParse);    
        parseReports(doc.getRootElement(), reports);
        return reports;
    }

    private void parseReports(DOM.XMLNode node, List<MonthlyReport> reports) {
        for (Dom.XMLNode child : node.getChildElements()) {
            if (child.getName() == 'monthlyReport') {
                MonthlyReport r = new MonthlyReport();
                parseReport(child, r);
                reports.add(r);
            }
        }
    }

    private void parseReport(DOM.XMLNode node, MonthlyReport r) {
        for (Dom.XMLNode child : node.getChildElements()) {
            if (child.getName() == 'month') {
                r.month = child.getText().trim();
            } else if (child.getName() == 'year') {
                r.year = child.getText().trim();
            } else if (child.getName() == 'weeklyRate') {
                r.weeklyRate = Decimal.valueOf(child.getText().trim());
            }
        }
    }
}

Using a separate method for each node type keeps each method fairly simple by it dealing with one level of the XML only.

  • This is great information. I had to tweak it just a bit to move through the nodes but got exactly what I wanted! Thank you for sharing your expertise!! – Berg Nov 10 '14 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.