Basic XML parsing issues. Cannot find node names v

2019-08-11 04:14发布

问题:

Having no luck in parsing some basic XML. I'm doing this in the Apex language, but it's syntactically nearly identical to Java and in this case uses java.xml.stream.XMLStreamReader as its XML parsing engine.

The problem is: 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.

code is here

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()).

Any ideas why? I'm stuck with the XML arriving in the format it's in...so I have to parse it as-is. I could use various workarounds (regEx, counting nodes, etc.) but those are messy and not ideal.

回答1:

I have reformed your code into one block that can be tested in the workbench's anonymous execution window. I run the code and then filter the Execution Log to show USER_DEBUG statements. The output shows node names and text as you would expect. I think the key is to use the APEX methods hasText() and hasName().

    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>';

XmlStreamReader reader = new XmlStreamReader(XML_STR);

while (reader.hasNext()) {
System.debug('$$$ reader.getEventType(): ' + reader.getEventType());
if (reader.hasName()) {
    System.debug('$$$ reader.getLocalName(): ' + reader.getLocalName());
//  System.debug('$$$ reader.getNamespace(): ' + reader.getNamespace());
//  System.debug('$$$ reader.getprefix(): ' + reader.getprefix());  
}
if (reader.hasText()) {
    System.debug('$$$ reader.getText(): ' + reader.getText());
}
System.debug('$$$ Go to next');
reader.next();
}

Here is another solution based on the recipe by Jon Mountjoy http://developer.force.com/cookbook/recipe/parsing-xml-using-the-apex-dom-parser

private String walkThrough(DOM.XMLNode node) {
  String result = '\n';
  if (node.getNodeType() == DOM.XMLNodeType.COMMENT) {
    return 'Comment (' +  node.getText() + ')';
  }
  if (node.getNodeType() == DOM.XMLNodeType.TEXT) {
    return 'Text (' + node.getText() + ')';
  }
  if (node.getNodeType() == DOM.XMLNodeType.ELEMENT) {
    result += 'Element: ' + node.getName();
    if (node.getText().trim() != '') {
      result += ', text=' + node.getText().trim();
    }
    if (node.getAttributeCount() > 0) { 
      for (Integer i = 0; i< node.getAttributeCount(); i++ ) {
        result += ', attribute #' + i + ':' + node.getAttributeKeyAt(i) + '=' + node.getAttributeValue(node.getAttributeKeyAt(i), node.getAttributeKeyNsAt(i));
      }  
    }
    for (Dom.XMLNode child: node.getChildElements()) {
      result += walkThrough(child);
    }
    return result;
  }
  return '';  //should never reach here 
}

private String parse(String toParse) {
  DOM.Document doc = new DOM.Document();      
  try {
    doc.load(toParse);    
    DOM.XMLNode root = doc.getRootElement();
    return walkThrough(root);

  } catch (System.XMLException e) {  // invalid XML
    return e.getMessage();
  }
}

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>';
System.debug(parse(XML_STR));