Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

XMLLib for PUGXML with XPath

, 29 Oct 2009
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)

Share

About the Author

JCrane2
Web Developer
United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 29 Oct 2009
Article Copyright 2003 by JCrane2
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid