function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
doubleminusdoubleminus 

XmlStreamReader processing issues. getLocalName() method always returning null. Why??

I'm using Apex to perform some basic XML parsing. I'm having no luck getting to any of the actual XML node names. The getLocalName()  method within the XmlStreamReader class always returns null for all nodes as I loop through them.

 

TEST CLASS:

@isTest
private class BPTCalloutTest {
private static final String XML_STR = '<document>' +
'<result>success</result>' +
'<resultcode>000000</resultcode>' +
'<note></note>' +
                                        '<item>' +
      '<quantity>1</quantity>' +
  '<fname>Bob</fname>' +
  '<lname>Tungsten</lname>' +
  '<address>23232 Fleet Street</address>' +
  '<city>Santa Clara</city>' +
  '<state>CA</state>' +
  '<zip>94105</zip>' +
  '<country>United States</country>' +
  '<email>blahblahblah@blahblahblah.com</email>' +
  '<phone>4155555555</phone>' +
    '</item>' +
  '</document>';
 
    static testMethod void xmlStreamReaderTest() {
        XmlStreamReader reader = new XmlStreamReader(XML_STR);
        Opportunity[] opptyList = BPTCallout.parseXML(reader);
        System.assert(opptyList != null);
        System.assert(!opptyList.isEmpty());
    }
}

 

MAIN CLASS:

public with sharing class BPTCallout {
    public BPTCallout() {}

    public static Opportunity[] parseXML(XmlStreamReader reader) {
        Opportunity[] oppList = new List<Opportunity>();

        if (reader != null) {
            while (reader.hasNext()) {
            	System.debug('$$$ reader.getEventType(): ' + reader.getEventType());
                if (reader.getEventType() == XmlTag.END_DOCUMENT) {
                    break;
                }
                else if (reader.getEventType() == XmlTag.CHARACTERS) {
                	System.debug('$$$ reader.getLocalName(): ' + reader.getLocalName());
                	System.debug('$$$ reader.getText(): ' + reader.getText());
                	System.debug('$$$ reader.getNamespace(): ' + reader.getNamespace());
                	System.debug('$$$ reader.getlocation(): ' + reader.getlocation());
                	System.debug('$$$ reader.getprefix(): ' + reader.getprefix());
                	
                	if (/*reader.getLocalName() == 'lname'*/ reader.getAttributeCount() == 4 && reader.getText() != null) {
	                    oppList.add(new Opportunity(Name = reader.getText()));
                	}
                }
                reader.next();
            }
        }
        System.debug('$$$ oppList: ' + oppList);
        return oppList;
    }
}

 

Very basic functionality at this point. If you run this, you will see that reader.getLocalName() always returns null and so do all accompanying methods (getNameSpace, getLocation, getPrefix).

 

Thanks in advance.

 

Best Answer chosen by Admin (Salesforce Developers) 
vishal@forcevishal@force

I think you are not using the methods in their correct order, which while parsing is very important.

 

Try this

 

public static Opportunity[] parseXML(XmlStreamReader reader) {
Opportunity[] oppList = new List<Opportunity>();

if (reader != null){
while (reader.hasNext()){
if(reader.getEventType() == XmlTag.END_DOCUMENT){
break;
}
else if(reader.getEventType() == XmlTag.START_ELEMENT){
if(reader.getLocalName() == 'lname'){
while(reader.hasNext()){
if (reader.getEventType() == XmlTag.END_ELEMENT){
break;
}
else if (reader.getEventType() == XmlTag.CHARACTERS){
System.debug('$$$ reader.getText(): ' + reader.getText());
System.debug('$$$ reader.getNamespace(): ' + reader.getNamespace());
System.debug('$$$ reader.getlocation(): ' + reader.getlocation());
System.debug('$$$ reader.getprefix(): ' + reader.getprefix());
oppList.add(new Opportunity(Name = reader.getText()));
}
reader.next();
}
}
}
reader.next();
}
}
System.debug('$$$ oppList: ' + oppList);
return oppList;
}

All Answers

vishal@forcevishal@force

I think you are not using the methods in their correct order, which while parsing is very important.

 

Try this

 

public static Opportunity[] parseXML(XmlStreamReader reader) {
Opportunity[] oppList = new List<Opportunity>();

if (reader != null){
while (reader.hasNext()){
if(reader.getEventType() == XmlTag.END_DOCUMENT){
break;
}
else if(reader.getEventType() == XmlTag.START_ELEMENT){
if(reader.getLocalName() == 'lname'){
while(reader.hasNext()){
if (reader.getEventType() == XmlTag.END_ELEMENT){
break;
}
else if (reader.getEventType() == XmlTag.CHARACTERS){
System.debug('$$$ reader.getText(): ' + reader.getText());
System.debug('$$$ reader.getNamespace(): ' + reader.getNamespace());
System.debug('$$$ reader.getlocation(): ' + reader.getlocation());
System.debug('$$$ reader.getprefix(): ' + reader.getprefix());
oppList.add(new Opportunity(Name = reader.getText()));
}
reader.next();
}
}
}
reader.next();
}
}
System.debug('$$$ oppList: ' + oppList);
return oppList;
}

This was selected as the best answer
RamitRamit

Hi,

 

Actually you are not traversing element by element.

 

First we need to identify that it is a Start Element then, check for the LocalName.If the LocalName matches then, in the next iteration we are checking if the element followed by LocalName is Character, if yes, then we get the text value of that element.

 

Please see the corrected code below :

 

public with sharing class BPTCallout 
{
    public BPTCallout() {}

    public static Opportunity[] parseXML(XmlStreamReader reader) 
    {
        Opportunity[] oppList = new List<Opportunity>();
        boolean check = false;
        if (reader != null) 
        {
                while (reader.hasNext()) 
                {
                    if (reader.getEventType() == XmlTag.END_DOCUMENT) 
                    {
                        break;
                    }
                    else if (reader.getEventType() == XmlTag.START_ELEMENT) 
                    {
                        if (reader.getLocalName()== 'lname')
                        {
                            check = true;
                        }
                        
                    }
                    if(check == true)
                    {
                        if(reader.getEventType() == XmlTag.CHARACTERS)
                        {
                            oppList.add(new Opportunity(Name = reader.getText()));
                            check = false;
                        }
                    }
                    reader.next();
                }
        }
        System.debug('$$$ oppList: ' + oppList);
        return oppList;
    }
}

 Let me know in case of any issues.

doubleminusdoubleminus

Thank you, Vishal and Ramit. Great solutions! I understand this functionality better now.

RamitRamit

You are welcome doubleminus!