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 Answer 1

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.

1
  • 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
    Commented Nov 10, 2014 at 13:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .