Click here to Skip to main content
11,412,834 members (73,700 online)
Click here to Skip to main content

XMLite: simple XML parser.

, 11 Oct 2004 CPOL
Rate this:
Please Sign up or sign in to vote.
Easy to access and simple XML parser

Sample Image - XMLite1.gif

Why XMLite?

In my previous project, I needed some simple XML parser. I worked with Jabber server. Because I had no time I worked with Jabber client library called Jabbercom, a Win32 COM based DLL module. Jabber protocol is based on XML. But that library was not a complete XML parser for my project.

First, it couldn't support Korean text (maybe other languages too) and there is no escape character processing, and no entity encode/decode supports. I had to replace XML parser engine, but I can't use MSXML and Expat, and it had a heavy installation or was hard to use. So I decided to make XMLite. It is not a fully supported XML parser, but it is simple and small, so I hope it helps someone.

Using XMLite

Simply, XMLite has two main data structures, XNode and XAttr. XNode is for XML element node and XAttr is for XML attribute node. XNode has child XNodes and own attributes list XAttrs. If you see my source code, you'll think code is so easy to understand and use. The code is simple.

  1. XML parsing

    XMLite can parse one XML tag node plain text like below. You can check for parsing error. If XNode::Load returns NULL, then simply you can know plain XML text has some error. If you want to know more error information, then go to section 4 - error handling.

    CString sxml;
    sxml = _T("\
    <TAddress desc='book of bro'>\
    <TPerson type='me'><Name>Cho,Kyung Min</Name><Nick>bro</Nick></TPerson>\
    <TPerson type='friend'><Name>Baik,Ji Hoon</Name><Nick>bjh</Nick></TPerson>\
    <TPerson type=friend><Name>Bak,Gun Joo</Name><Nick>dichter</Nick></TPerson>\
    <TInformation count='3'/>\
    </TAddress>");
    
    XNode xml;
    if( xml.Load( sxml ) )
        AfxMessageBox(xml.GetXML());
    else
        AfxMessageBox(_T("error")); // simple parsing error check

    The result is shown in the picture above.

  2. Traveling with parsed XML

    CString sxml;
    sxml = _T("\
    <TAddressBook description=\"book of bro\">\
    <TPerson type='me'><Name>Cho,Kyung Min</Name><Nick>bro</Nick></TPerson>\
    <TPerson type='friend'><Name>Baik,Ji Hoon</Name><Nick>bjh</Nick></TPerson>\
    <TPerson type=friend><Name>Bak,Gun Joo</Name><Nick>dichter</Nick></TPerson>\
    <TInformation count='3'/>\
    </TAddressBook>");
    
    XNode xml;
    xml.Load( sxml );
    
    int i;
    XNodes childs;
    
    // DOM tree Childs Traveling 
    // method 1: Using GetChildCount() and GetChild()
    // Result: Person, Person, Person, Information
    LPXNode child;
    for( i = 0 ; i < xml.GetChildCount(); i++)
    {
        child = xml.GetChild(i);
        AfxMessageBox( child->GetXML() );
    }
    
    // method 2: LPXNodes and GetChilds() ( same result with method 1 )
    // Result: Person, Person, Person, Information
    childs = xml.GetChilds();
    for( i = 0 ; i < childs.size(); i++)
        AfxMessageBox( childs[i]->GetXML() );
    
    // method 3: Selected Childs with GetChilds()
    // Result: Person, Person, Person
    childs = xml.GetChilds(_T("Person") );
    for( i = 0 ; i < childs.size(); i++)
    {
        AfxMessageBox( childs[i]->GetXML() );
    }
    
    // method 4: Get Attribute Vaule of Child
    // Result: 3
    AfxMessageBox( xml.GetChildAttrValue( _T("Information"), _T("count") ) );
    int count = XStr2Int( xml.GetChildAttrValue( _T("Information"), 
                                                         _T("count") ));
    ASSERT( count == 3 );
  3. DOM Modify

    CString sxml;
    sxml = _T("\
    <TAddressBook description=\"book of bro\">\
    <TPerson type='me'><Name>Cho,Kyung Min</Name><Nick>bro</Nick></TPerson>\
    <TPerson type='friend'><Name>Baik,Ji Hoon</Name><Nick>bjh</Nick></TPerson>\
    <TPerson type=friend><Name>Bak,Gun Joo</Name><Nick>dichter</Nick></TPerson>\
    <TInformation count='3'/>\
    </TAddressBook>");
    
    XNode xml;
    xml.Load( sxml );
    
    // remove 'bro node'
    LPXNode child_bro = xml.GetChild(0);
    xml.RemoveChild( child_bro );
    
    AfxMessageBox(xml.GetXML());

    Result: there is no bro node.

    <TAddressBook description='book of bro' >
        <TPerson type='friend' >
            <Name>Baik,Ji Hoon</Name>
            <Nick>bjh</Nick>
        </TPerson>
        <TPerson type='friend' >
            <Name>Bak,Gun Joo</Name>
            <Nick>dichter</Nick>
        </TPerson>
        <TInformation count='3' />
    </TAddressBook>
  4. Error Handling

    XMLite has xml error handling, but it's not complete.

    CString serror_xml;
    serror_xml = _T("<XML>\
    <NoCloseTag type='me'><Name>Cho,Kyung Min</Name><Nick>bro</Nick>\
    </XML>");
        
    XNode xml;
    PARSEINFO pi;
    xml.Load( serror_xml, &pi );
    
    if( pi.erorr_occur ) // is error_occur?
    {
        //result: '<NoCloseTag> ... </XML>' is not wel-formed.
        AfxMessageBox( pi.error_string );
        AfxMessageBox( xml.GetXML()  );
    }
    else
        ASSERT(FALSE);

    then, result is

    '<NoCloseTag> ... </XML>' is not wel-formed.
  5. Entity and Escape Char Test

    XMLite has escape process. But this updated version has no escape for general case. But still you can use escape character with parsing value.

    pi.escape_value = '\\' 

    Upper case, escape character is:

    '\'
    like C/C++. And it has entity processing. Entity table is like shown below:
    Special character Special meaning Entity encoding
    > Begins a tag. >
    < Ends a tag. <
    " Quotation mark. "
    ' Apostrophe. &apos;
    & Ampersand. &
    CString sxml;
    sxml = _T("<XML>\
    <TAG attr='<\\'asdf\\\">'>asdf</TAG>\
    </XML>");
    
    XNode xml;
    PARSEINFO pi;
    pi.escape_value = '\\'  // using escape character on value string
    xml.Load( sxml, &pi );
    
    AfxMessageBox( xml.GetXML()  );

    Result:

    <XML>
        <TAG attr='<&apos;asdf">' >asdf</TAG>
    </XML>
  6. Configurate Parse and Display

    XMLite can trim when parsing and add newline for display (default).

    CString sxml;
    sxml = _T("<XML>\
    <TAG attr='   qwer      '>        asdf       </TAG>\
    </XML>");
    
    XNode xml;
    
    xml.Load( sxml );
    AfxMessageBox( xml.GetXML()  );
    
    PARSEINFO pi;
    pi.trim_value = true; // trim value
    xml.Load( sxml, &pi );
    AfxMessageBox( xml.GetXML()  );
    
    DISP_OPT opt;
    opt.newline = false; // no new line
    
    AfxMessageBox( xml.GetXML( &opt )  );

    Result:

    first,

    <XML>
        <TAG attr='   qwer      ' >        asdf       </TAG>
    </XML>

    after,

    <XML><TAG attr='qwer' >asdf</TAG></XML>
  7. Custom entity table

    XMLite can customize entity table for special parsing and display. You can define new entity table for customized parsing.

    CString sxml;
    sxml = _T("<XML>\
    <TAG attr='&asdf>'></TAG>\
    </XML>");
    
    // customized entity list
    static const XENTITY entity_table[] = {
            { '<', _T("<"), 4 } ,
            { '&', _T("&"), 5 }
        };
    XENTITYS entitys( (LPXENTITY)entity_table, 2 ) ;
    
    PARSEINFO pi;
    XNode xml;
    pi.entity_value = true; // force to use custom entitys
    pi.entitys = &entitys;
    xml.Load( sxml, &pi );
    AfxMessageBox( xml.GetXML()  );
    
    DISP_OPT opt;
    opt.entitys = &entitys;
    opt.reference_value = true; // force to use custom entitys
    
    AfxMessageBox( xml.GetXML( &opt )  );
  8. branch copy (deep-copy)

    Now XMLite can copy branch.

    void CTestXMLiteDlg::OnButton9() 
    {
        // TODO: Add your control notification handler code here
        CString sxml;
        sxml = _T("<addressbook description=""\"</span>book"" />\
    <person type=""me"" /><NAME>Cho,Kyung Min</NAME><NICK>bro</NICK></person />\
    <person type=""friend"" /><NAME>Baik,Ji Hoon</NAME><NICK>bjh</NICK></person />\
    <person type=""friend"" /><NAME>Bak,Gun Joo</NAME><NICK>dichter</NICK></person />\
    <information count=""3"" />\
    </addressbook />");
    
        XNode xml;
        xml.Load( sxml );
        AfxMessageBox( xml.GetXML()  );
    
            // copy one level node with its own attributes
        XNode xml2;
        xml2.CopyNode( &xml );
        AfxMessageBox( xml2.GetXML()  );
           
            // copy branch of other node (deep-copy)
        XNode xml3;
        //same with xml3 = xml;
        xml3.CopyBranch( &xml );
        AfxMessageBox( xml3.GetXML()  );
    
            // append copied-branch of other node as my child
        XNode xml4;
        //same with xml3.CopyBranch( &xml );
        xml4.AppendChildBranch( &xml );
        AfxMessageBox( xml4.GetXML()  );
    }
    
  9. Parsing xml with PI/CDATA/Comment

    Now XMLite can parse with PI/CDATA/Comment. But Still XMLite doesn't support PI's encoding function.

    void CTestXMLiteDlg::OnButton10() 
    {
     // TODO: Add your control notification handler code here
     CString sxml;
     sxml = _T("<?xml version='1.0'?>\
    \
    <![CDATA[some data]]>\
    <a>\
     <![CDATA[some data]]>\
     value\
     <![CDATA[some data2]]>\
    </a><!-- comment2-->");
     
     XNode xml;
     xml.Load( sxml );
    
     AfxMessageBox( xml.GetXML()  );
    }
  10. Parsing un-welformed xml (like HTML)

    Now XMLite can parse un-welformed xml like HTML with 'force_parse' attribute

    void CTestXMLiteDlg::OnButton11() 
    {
     // TODO: Add your control notification handler code here
     CString sXML = "\
    < html>\
      < body width='100'>\
         Some times I got say...\
      \
      \
      < p>\
      Thanks\
      < /body>\
    < /html>";
    
     XDoc xml;
    
     PARSEINFO pi;
     pi.force_parse = true;
     if( xml.Load( sXML, &pi ) )
     {
      LPXNode root = xml.GetRoot();
      //root->AppendChild( _T("child"), _T("value") );
      AfxMessageBox( xml.GetXML() );
     }
    
     // you can't not parse without force_parse on un-welformed xml!
     XNode node;
     if( node.Load( sXML ) )
     {
      AfxMessageBox( node.GetXML() );
     } 
    }
  11. Deep-Find

    XMLite's node can search own all children with tag name.

    CString sXML = "\
    <a>\
     
      \
     
      <C/>\
     
      <D/>\
     
      \
    </a>";
    
     XNode node;
     if( node.Load( sXML ) )
     {
      AfxMessageBox( node.GetXML() );
    
      LPXNode found = NULL;
      found = node.Find( _T("D") );
      if( found )
      {
       AfxMessageBox( found->GetXML() );
      }
     }

History

// XMLite : XML Lite Parser Library
// by bro ( Cho,Kyung Min: bro@shinbiro.com ) 2002-10-30
// History.
// 2002-10-29 : First Coded. Parsing XMLElelement and Attributes.
//              get xml parsed string ( looks good )
// 2002-10-30 : Get Node Functions, error handling ( not completed )
// 2002-12-06 : Helper Funtion string to long
// 2002-12-12 : Entity Helper Support
// 2003-04-08 : Close,
// 2003-07-23 : add property escape_value. (now no escape on default)
// 2003-10-24 : bugfix) attribute parsing <TAG \r\n a="1" /> is now ok
// 2004-03-05 : add branch copy functions

License

Sometimes I get email about license of XMLite. You can use/modify/redistribute XMLite for commercial/noncomercial. But please give me thanks email with your project information.
Then I will be happy and add it to references of XMLite. If you fix or update XMLite then give it to me for all to have. Thanks.

Reference

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Cho, Kyung-min
Software Developer
Korea (Republic Of) Korea (Republic Of)
No Biography provided

Comments and Discussions

 
QuestionLicense CPOL Pin
Member 11115243 at 28-Sep-14 1:14
memberMember 1111524328-Sep-14 1:14 
Bugwellformed tab indentation with opt.newline = true / SaveFile and LoadLoad functions [modified] Pin
Thomas Mielke at 14-Jun-14 8:51
memberThomas Mielke14-Jun-14 8:51 
QuestionThanks ! it is a good tool for me! Pin
marsfreak at 2-Apr-12 22:45
membermarsfreak2-Apr-12 22:45 
QuestionVisual Studio 2008 Pin
william basser at 6-Jul-11 8:57
memberwilliam basser6-Jul-11 8:57 
Great job on software.

Have you ever attempted to compile with Vusal Studio 2008? I am running into errors with _c:\temp\xmlite_demo\xmlite.cpp(1425) : error C2664: 'std::_Vector_iterator<_Ty,_Alloc>::_Vector_iterator(const std::_Vector_iterator<_Ty,_Alloc> &)' : cannot convert parameter 1 from 'int' to 'const std::_Vector_iterator<_Ty,_Alloc> &'
1> with
1> [
1> _Ty=LPXNode ,
1> _Alloc=std::allocator<LPXNode >
1> ]
1> Reason: cannot convert from 'int' to 'const std::_Vector_iterator<_Ty,_Alloc>'
1> with
1> [
1> _Ty=LPXNode ,
1> _Alloc=std::allocator<LPXNode >
1> ]

Any suggestions?
AnswerRe: Visual Studio 2008 Pin
Thomas Mielke at 13-Feb-14 3:35
memberThomas Mielke13-Feb-14 3:35 
GeneralXML String without ⎡ Pin
fonny at 28-Feb-10 22:49
memberfonny28-Feb-10 22:49 
GeneralPure C Version Pin
Igino M Chaves at 19-Jan-10 2:25
memberIgino M Chaves19-Jan-10 2:25 
GeneralXMLite ANSI to UNICODE conversion [modified] Pin
Theo Buys at 14-Jan-10 4:48
memberTheo Buys14-Jan-10 4:48 
GeneralBug in GetAttrs function. Pin
Priya_Sundar at 7-Jan-10 0:51
memberPriya_Sundar7-Jan-10 0:51 
GeneralRe: Bug in GetAttrs function. Pin
Theo Buys at 14-Jan-10 22:07
memberTheo Buys14-Jan-10 22:07 
GeneralUnicode version of XMLite Pin
G.Muruganandam at 30-Nov-09 16:40
memberG.Muruganandam30-Nov-09 16:40 
GeneralRe: Unicode version of XMLite Pin
Theo Buys at 14-Jan-10 22:13
memberTheo Buys14-Jan-10 22:13 
QuestionIs it possible to create childs that over the 5 deeps..? Pin
zzigee at 17-Aug-09 18:00
memberzzigee17-Aug-09 18:00 
AnswerRe: Is it possible to create childs that over the 5 deeps..? Pin
Cho, Kyung-min at 17-Aug-09 20:47
memberCho, Kyung-min17-Aug-09 20:47 
QuestionWin CE Version Pin
infosarang at 29-Apr-09 0:16
memberinfosarang29-Apr-09 0:16 
Questiongnu gcc version of this? Pin
noone23 at 16-Mar-09 14:55
membernoone2316-Mar-09 14:55 
AnswerRe: gnu gcc version of this? Pin
infosarang at 27-Mar-09 2:18
memberinfosarang27-Mar-09 2:18 
AnswerRe: gnu gcc version of this? Pin
Cho, Kyung-min at 17-Aug-09 21:20
memberCho, Kyung-min17-Aug-09 21:20 
Generalnice, but. Pin
malleor at 13-Mar-09 6:27
membermalleor13-Mar-09 6:27 
GeneralRe: nice, but. but but but. Pin
malleor at 13-Mar-09 8:08
membermalleor13-Mar-09 8:08 
GeneralThanks a lot! Pin
snowtiger9127 at 12-Mar-09 21:15
membersnowtiger912712-Mar-09 21:15 
QuestionXMLite not compiled in VC++ 2005 Pin
infosarang at 22-Feb-09 23:24
memberinfosarang22-Feb-09 23:24 
AnswerRe: XMLite not compiled in VC++ 2005 Pin
infosarang at 22-Feb-09 23:54
memberinfosarang22-Feb-09 23:54 
GeneralRe: XMLite not compiled in VC++ 2005 Pin
Sadru at 11-Feb-10 20:03
memberSadru11-Feb-10 20:03 
GeneralThanks for using XMLite, Device Solutions LLC. Pin
Cho, Kyung-min at 18-Jan-09 14:39
memberCho, Kyung-min18-Jan-09 14:39 
QuestionHow to Create XML doc? Pin
Member 3673808 at 12-Dec-08 2:44
memberMember 367380812-Dec-08 2:44 
AnswerRe: How to Create XML doc? Pin
Cho, Kyung-min at 12-Dec-08 19:08
memberCho, Kyung-min12-Dec-08 19:08 
GeneralRe: How to Create XML doc? Pin
Member 3673808 at 15-Dec-08 5:27
memberMember 367380815-Dec-08 5:27 
GeneralVC2008 version of XMLite Pin
saflyer at 8-Dec-08 21:25
membersaflyer8-Dec-08 21:25 
GeneralRe: VC2008 version of XMLite Pin
Cho, Kyung-min at 12-Dec-08 18:58
memberCho, Kyung-min12-Dec-08 18:58 
GeneralRe: VC2008 version of XMLite Pin
Humanchao at 26-Sep-10 17:35
memberHumanchao26-Sep-10 17:35 
Questionthanks for xmllite !! another question :how to change the attribute value in a xml string ,and how to add a child to a xml string?? Pin
lw8401 at 17-Sep-08 17:05
memberlw840117-Sep-08 17:05 
AnswerRe: thanks for xmllite !! another question :how to change the attribute value in a xml string ,and how to add a child to a xml string?? [modified] Pin
Cho, Kyung-min at 17-Sep-08 18:26
memberCho, Kyung-min17-Sep-08 18:26 
GeneralRe: thanks for xmllite !! another question :how to change the attribute value in a xml string ,and how to add a child to a xml string?? Pin
lw8401 at 18-Sep-08 17:45
memberlw840118-Sep-08 17:45 
General[Message Removed] Pin
nompel at 20-Sep-08 15:56
membernompel20-Sep-08 15:56 
GeneralRe: thanks for xmllite !! another question :how to change the attribute value in a xml string ,and how to add a child to a xml string?? Pin
Cho, Kyung-min at 20-Sep-08 21:37
memberCho, Kyung-min20-Sep-08 21:37 
QuestionCan xmlite Load xml files ??such as temp.xml?? Pin
lw8401 at 26-Aug-08 22:21
memberlw840126-Aug-08 22:21 
AnswerRe: Can xmlite Load xml files ??such as temp.xml?? Pin
Cho, Kyung-min at 27-Aug-08 14:09
memberCho, Kyung-min27-Aug-08 14:09 
GeneralThanks for using xmlite Pin
Cho, Kyung-min at 30-Jul-08 7:47
memberCho, Kyung-min30-Jul-08 7:47 
GeneralReading XML Data from an URL Pin
T.RATHA KRISHNAN at 15-May-08 2:04
memberT.RATHA KRISHNAN15-May-08 2:04 
GeneralRe: Reading XML Data from an URL Pin
Cho, Kyung-min at 19-May-08 14:32
memberCho, Kyung-min19-May-08 14:32 
QuestionHow to read an xml file? Pin
iyadounove at 19-Apr-08 5:45
memberiyadounove19-Apr-08 5:45 
AnswerRe: How to read an xml file? Pin
Cho, Kyung-min at 19-May-08 14:35
memberCho, Kyung-min19-May-08 14:35 
GeneralAnybody used this parser on Mobile Pin
zoomesh at 9-Apr-08 22:58
memberzoomesh9-Apr-08 22:58 
GeneralRe: Anybody used this parser on Mobile Pin
LittleIan at 30-Jul-08 2:32
memberLittleIan30-Jul-08 2:32 
GeneralCDATA Pin
LittleIan at 23-Jan-08 2:01
memberLittleIan23-Jan-08 2:01 
GeneralRe: CDATA Pin
Cho, Kyung-min at 19-May-08 14:49
memberCho, Kyung-min19-May-08 14:49 
GeneralRe: CDATA Pin
LittleIan at 30-Jul-08 2:21
memberLittleIan30-Jul-08 2:21 
GeneralVisual Studio 2005 Pin
alex28273 at 13-Dec-07 15:00
memberalex2827313-Dec-07 15:00 
GeneralI get error Pin
Member 4684276 at 2-May-08 1:58
memberMember 46842762-May-08 1:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150427.1 | Last Updated 11 Oct 2004
Article Copyright 2002 by Cho, Kyung-min
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid