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
PRepakaPRepaka 

XML Parsing

hi

 

can u please help me how to parse an XML.

 

Actually my requirement is create a webservice in APEX. The parameter for webservice is in the form of XML String. in that webservice i have to parse that XML. for example my input xml is in the form of

 

<?xml version="1.0" encoding="UTF-8" ?>
- <Body>
- <InvoiceRequest>
- <Item>
  <ItemName>num1</ItemName>
  <ItemPrice>$11.0</ItemPrice>
  <ItemId>01278390921098209AB872190</ItemId>
  <ItemType>NULL</ItemType>
  </Item>
- <Item>
  <ItemName>Misc. Service</ItemName>
  <ItemPrice>$23.0</ItemPrice>
  <ItemId>NULL</ItemId>
  <ItemType>Service</ItemType>
  </Item>
- <Item>
  <ItemName>Misc. Product</ItemName>
  <ItemPrice>$36.0</ItemPrice>
  <ItemId>NULL</ItemId>
  <ItemType>Product</ItemType>
  </Item>
  </InvoiceRequest>
  </Body>

 

for the above XML how can i parse this xml. Please help me. The above xml is related to Item Custom object. so i have to construct a List<Item__c> object for this XML.

 

 

Please help me.

jhenningjhenning

use the xmlstreamreader class

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_XmlStream_reader.htm

 

here is a class that wraps it:

 

 

/* Copyright (c) 2008 salesforce.com, inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* This class implements a small portion of the wc3 xml dom model. Generally useful for simple XML return objects. Note: stores namespaces in the attributes map for now. No node typing done at this time can parse into DOM trees the XML return objects from Google, Amazon and others. large parse trees will consume suprising amounts of memory */ public class XMLDom { // Constructor public XMLDom(string str) { parseFromString(str); } public XMLDom( ) { } public void parseFromString(string str) { XmlStreamReader reader = new XmlStreamReader(str); reader.setCoalescing(true); parseXmlReader (root , reader); } // debugging assistance public void dumpAll() { root.dumpAll(); } public void dumpList(Element[] l) { for(Element e:l) e.dump(); } // given a parent node and a stream reader, populates the tree below here (recursive) void parseXmlReader( Element parent, XmlStreamReader reader ) { try { while(reader.hasNext()) { if (reader.getEventType() == XmlTag.START_ELEMENT) { string nodeName = reader.getLocalName(); string pre = reader.getPrefix(); if ( pre != null && pre != '' ) { //system.debug( reader.getPrefix() ); nodeName = reader.getPrefix() + ':' + nodeName; } Element child = new Element( nodeName ); // add all attributes from this element for (integer i=0; i<reader.getAttributeCount(); i++) { child.attributes.put( reader.getAttributeLocalName(i), reader.getAttributeValueAt(i) ); } // add namespace info to each node/element ( for now storing on attributes map) for (integer j=0; j<reader.getNamespaceCount(); j++) { string prefix = 'xmlns'; if (reader.getnamespaceprefix(j)!=null) prefix = reader.getnamespaceprefix(j); child.attributes.put( prefix , reader.getnamespaceuriat(j) ); } parent.appendChild(child); // add the new element to current parent reader.next(); parseXmlReader(child, reader) ; // recurse } else if (reader.getEventType() == XmlTag.END_ELEMENT) { reader.next(); return; } else if (reader.getEventType() == XmlTag.CHARACTERS) { if ( ! reader.isWhitespace()) { parent.nodeValue += reader.getText(); // add text to current element } reader.next(); } else { reader.next(); } } } catch(Exception e) { // ParseError if we get a truncated response, allow it system.debug(e); } } // access nodes in the tree using these getters public List<Element> getElementsByTagName(string nam) { return root.getElementsByTagName(nam); } public Element getElementByTagName(string nam) { List<Element> r = root.getElementsByTagName(nam); if (r.size() == 0) return null; return r[0]; } // utility dom functions public Element ownerDocument() { return root; } // everything in the dom is found as childNodes under this root element public Element root = new Element('#document'); public integer debug =0; // dump out the element tree public String toXmlString() { return root.toXmlString(); } /* * Element class definition This following class implements a small portion of the wc3 xml dom model. Generally useful for simple XML return objects. for a properties and methods complete list see: http://www.w3schools.com/dom/dom_node.asp For simplicity, Nodes are the same as Elements in this class. Nodes have text directly in them, rather than a seperate text node child The following describes the implemented portion, some w3c properties are now methods. Property Description nodeName Returns the name of a node, depending on its type nodeValue Sets or returns the value of a node, depending on its type childNodes Returns a NodeList of child nodes for a node parentNode Returns the parent node of a node attributes Returns a NamedNodeMap of attributes for the element, also contains name space entries getElementByTagName() Returns list of elements matching tag name (document and element) firstChild() Returns the first child of a node removeChild() Removes a child node appendChild() Adds a new child node to the end of the list of children of a node getAttribute() Returns the value of an attribute hasChildNodes() Returns whether the element has any child nodes isEqualNode() Checks if two nodes are equal textContent() returns the textual content of a node cloneNode() Clones a node hasAttributes() Returns whether the element has any attributes isSameNode() Checks if two nodes are the same node ownerDocument() Returns the root element (document object) for a node *** NOT Implemented at this time *** lastChild() Returns the last child of a node nodeType Returns the type of a node , all nodes are the same type currently baseURI Returns the absolute base URI of a node localName Returns the local part of the name of a node namespaceURI Returns the namespace URI of a node nextSibling Returns the node immediately following a node insertBefore() Inserts a new child node before an existing child node replaceChild() Replaces a child node */ public class Element { // Element(Element p, string n) { parentNode = p; nodeName = n; } public Element(string n) { nodeName = n; } public Element() { } public string getAttribute(string name) { return attributes.get(name); } public void appendChild(Element e) { e.ParentNode = this; this.childNodes.add(e); } public void removeChild(Element e) { Element p = e.parentNode; List<Element> kids = new List<Element> {}; for( Element ee: e.parentNode.childNodes) { if (ee != e) kids.add(ee); } p.childNodes = kids; } // traverse below this node, returning all matching nodes by name public List<Element> getElementsByTagName(string nam) { List<Element> ret = new List<Element>{}; if (nam == this.nodeName) ret.add(this); for (Element c: this.childNodes) { ret.addAll( c.getElementsByTagName(nam) ); // decend tree } return ret; } // like above, but just returns the first one that matches public Element getElementByTagName(string nam) { List<Element> r = getElementsByTagName(nam); if (r.size() == 0) return null; return r[0]; } // first one that matches, just return the nodeValue public string getValue(string nam) { Element e = getElementByTagName(nam); return (e==null?null:e.nodeValue); } // some debugging help public void dump() { dump('');} public void dump(string pre) { // just current node system.debug( pre + ' ' +this.nodeName + '->' + this.nodeValue + ' ' + this.attributes ); } public void dumpAll() { dumpAll(''); } public void dumpAll(string pre) { // node and all children system.debug( pre + this.nodeName + '->' + this.nodeValue + ' ' + this.attributes ); for (Element c: this.childNodes) { c.dumpAll(pre+' '); } } public string toXmlString() { string ret = '<' + this.nodeName + ' '; for ( string a : attributes.keySet() ) { ret += a + '=\'' + attributes.get(a) + '\' ' ; } ret += '>'; if (nodeValue == '' ) ret += '\n'; for (Element c: this.childNodes) { ret += c.toXmlString() ;//+ '\n'; } if (nodeValue != '' ) ret += nodeValue; //else ret += '\n'; return ret + '</' + this.nodeName + '>\n'; } /* * experimental path based patern matching, sort of like xpath, * but simpler, just matches a path() string with the pattern supplied */ // * /bookstore/book/.* // /.*book/.* // /.*/book$ public List<Element> getElementsByPath(string path) { List<Element> ret = new List<Element>{}; // system.debug( path + ' ' + this.path()); if ( Pattern.matches(path, this.path()) ) ret.add(this); for (Element c: this.childNodes) ret.addAll( c.getElementsByPath(path) ); return ret; } public string path() { Element t = this; string ret = t.nodeName; while (t.parentNode != null && t.parentNode.nodeName != '#document') { t = t.parentNode; ret = t.nodeName + '/'+ret; } return '/'+ret; } // utility methods public Element firstChild() { if ( this.childNodes.size() == 0 ) return null; return this.childNodes[0]; } public string textContent() { return this.nodeValue; } public boolean hasChildNodes() { return childNodes.size()>0; } public boolean isEqualNode(Element comp) { return this.nodeName == comp.nodeName; } public Element cloneNode() { return this.clone(); } public boolean hasAttributes() { return ! attributes.isEmpty(); } public boolean isSameNode(Element comp) { return this === comp; } public Element ownerDocument() { Element ret = this; while( ret.parentNode != null) { ret = ret.parentNode; } return ret; } // properties public Element parentNode = null; // only root has a null parent public string nodeName = ''; public string nodeValue = ''; public List<Element> childNodes = new List<Element>(); public map<String,String> attributes = new map<String,String>(); } }

 

 

 

 

 

Ramakrishnan AyyanarRamakrishnan Ayyanar
I created one simple XML Parsing.I have Used one VF page and Apex Class.It's parsing correctly ...

VF Page:

<apex:page Controller="Xmlparsar">

<apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons location="bottom">
                <apex:commandButton value="Parse Xml" action="{!Parsexml}" />  
                <apex:commandButton value="ParseXML File" action="{!Parsexmlfile}"/>
            </apex:pageBlockButtons>
            <apex:inputTextArea value="{!xmlstring}" style="width:336px;height:260px;"/> &nbsp;&nbsp;
            <apex:inputTextArea value="{!outxmlstring}" style="width:336px;height:260px;" id="response"/><br/>

            <apex:outputLabel value="Select Xml File" for="file"/>
            <apex:inputFile fileName="{!fileName}" value="{!body}"/>
        </apex:pageBlock>
    </apex:form>
  
</apex:page>

Apex Class:

public  class Xmlparsar
{
    //xml string
    public String xmlstring{get;set;}
  
    //display xml string
    public String outxmlstring{get;set;}
  
    //rootelement
    public String rootElement{get;set;}
  
    //
    public String filename{get;set;}
  
    public blob body{get;set;}
     
    //constructor
    public Xmlparsar()
    {
   
    }
  
   
//Parsing xml what you entered in the left text area
    public pagereference Parsexml()
    {
       DOM.Document xmlDOC = new DOM.Document();
       xmlDOC.load(xmlstring);
       DOM.XMLNode rootElement = xmlDOC.getRootElement();
       outxmlstring=String.valueof(xmlDOC.getRootElement().getName());
       for(DOM.XMLNode xmlnodeobj:xmlDOC.getRootElement().getChildElements())
       //.getChildren())
       {       
        
        
          loadChilds(xmlnodeobj);        
       }     
       return null;
    }
  
    //loading the child elements
    private void loadChilds(DOM.XMLNode xmlnode)
    {
        for(Dom.XMLNode child : xmlnode.getChildElements())
        {
          if(child.getText()!= null)
          {
          outxmlstring+='\n'+child.getName()+': '+child.getText();
      
          }
          loadChilds(child);      
        }
    }
  
  
//This is for parsing xml file what you selected
  public pagereference Parsexmlfile()
  {
       DOM.Document xmlDOC = new DOM.Document();
       xmlstring=body.tostring();        
       xmlDOC.load(xmlstring);
       DOM.XMLNode rootElement = xmlDOC.getRootElement();
       outxmlstring=String.valueof(xmlDOC.getRootElement().getName());//gives you root element Name
       for(DOM.XMLNode xmlnodeobj:xmlDOC.getRootElement().getChildElements())
       {       
                 
          loadChilds(xmlnodeobj);
       }     
      return null;
    }
}
Jennifer SimondsJennifer Simonds
I got frustrated trying to use XMLStreamReader & Dom.Document to parse XML files in Apex, so I wrote my own tiny XPath interpreter class. It's proven to be very useful for me. You can pass an XML string or a Dom.Document to the constructor, and then you just call some simple methods with an XPath to find any element, or list of elements, in the DOM.

Give it a try, and please let me know of any bugs, limitations, or suggestions.

https://github.com/JenniferSimonds/apex-xpath
 
Philip FPhilip F
Jennifer, you're my hero.  Your Apex XPath class was exactly what I was looking for.  Thank you!!!
Lawrence-AccentureLawrence-Accenture
Jennifer, thank you! Made writing a custom SOAP webservice integration much much easier!