Click here to Skip to main content
15,892,746 members
Articles / Programming Languages / XML

XMLLib for PUGXML with XPath

Rate me:
Please Sign up or sign in to vote.
4.33/5 (11 votes)
29 Oct 2009CPOL5 min read 126.4K   1.2K   38  
A library for PugXML which implements XPath
// PugXMLNode.cpp: implementation of the CPugXMLNode class.
// Copyright (C) 2003, by John Crane
//
//////////////////////////////////////////////////////////////////////

#define _CRT_SECURE_NO_WARNINGS 1

#include "PugXPathExpression.h"
#include "PugXMLNode.h"

// Include the Pug XML library.
#include "pugxml.h"
#include <sstream>

using namespace std;
using namespace pug;
using namespace blue::ext::xml;


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPugXMLNode::CPugXMLNode() : xml_node()
{
}

CPugXMLNode::CPugXMLNode(xml_node_struct* p) : xml_node(p)
{
}

CPugXMLNode::CPugXMLNode(const xml_node& r) : xml_node(r)
{
}

CPugXMLNode::~CPugXMLNode()
{
}

//
// Find all nodes that match a search string and return them
// in an Array of xml_node_struct*'s
//
Array<xml_node_struct*> CPugXMLNode::FindNodes(const char* srch)
{
    try
    {
        CAddAttributeNodes add;
        CDelAttributeNodes del;
        traverse(add);
        PugXPathExpression xpath(this->_root);
        Array<xml_node_struct*> nodes =  xpath.findNodes(srch);
        traverse(del);
        return nodes;
    }
    catch(XmlException e)
    {
        throw e.getDescription();
    }
}

//
// Find first matching node
//
xml_node_struct*  CPugXMLNode::FindNode(const char* srch)
{
    try
    {
        CAddAttributeNodes add;
        CDelAttributeNodes del;
        traverse(add);
        PugXPathExpression xpath(this->_root);
        CPugXMLNode node = CPugXMLNode(xpath.findNode(srch));
        traverse(del);
        return (xml_node_struct* ) node;
    }
    catch(XmlException e)
    {
        throw e.getDescription();
    }
}

//
// Return only matching values in an Array<BString>
//
Array<BString> CPugXMLNode::FindValues(const char* srch)
{
    try
    {
        CAddAttributeNodes add;
        CDelAttributeNodes del;
        traverse(add);
        PugXPathExpression xpath(this->_root);
        traverse(del);
        Array<BString> values = xpath.findValues(srch);
        return values;
    }
    catch(XmlException e)
    {
        throw e.getDescription();
    }
}

//
// Return first matching value
//
BString CPugXMLNode::FindValue(const char* srch)
{
    try
    {
        CAddAttributeNodes add;
        CDelAttributeNodes del;
        traverse(add);
        PugXPathExpression xpath(this->_root);
        BString value = xpath.findValue(srch);
        traverse(del);
        return value;
    }
    catch(XmlException e)
    {
        throw e.getDescription();
    }
}

//
// If a node contains attributes, add phoney child nodes
// representing attributes
//
bool CAddAttributeNodes::for_each(xml_node& node)
{
    if (node.has_attributes())
    {
        for (unsigned int i = 0; i < node.attributes(); i++)
        {
            // Set a type of node_element so we can add stuff
            xml_node attr = node.append_child(node_element);
            const TCHAR* pName = node.attribute(i).name();
            const TCHAR* pVal= node.attribute(i).value();
            attr.name(node.attribute(i).name());
            attr.append_child(node_pcdata).value(node.attribute(i).value());
            // Set the real type
            ((xml_node_struct*) attr)->type = node_attribute;
        }
    }

    return true; // Keep traversing.
}

//
// Remove phoney attribute nodes that we prveiously added
//
bool CDelAttributeNodes::for_each(xml_node& node)
{
    if (node.has_attributes())
    {
        bool bFound = false;

        do
        {
            bFound = false;
            for (unsigned int i = 0; i < node.children(); i++)
            {
                if (node.child(i).type() == node_attribute)
                {
                    bFound = true;
                    node.remove_child(i);
                    break;
                }
            }
        } while (bFound);
    }
    return true; // Keep traversing.
}

//
// Recursively append existing node and all its children
// 

void CPugXMLNode::AppendTree(xml_node& node)
{
    CPugXMLNode newNode = append_child(node.type());
    newNode.name(node.name());
    newNode.value(node.value());
    if (node.has_attributes() )
    {
        for (unsigned int i = 0; i < node.attributes(); i++)
        {
            newNode.append_attribute(node.attribute(i).name(), node.attribute(i).value());
        }
    }

    if (node.has_child_nodes())
    {
        for (unsigned int i = 0; i < node.children(); i++)
        {
            newNode.AppendTree(node.child(i));
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions