XdmfCoreReader.cpp 4.34 KB
Newer Older
1 2 3
// Kenneth Leiter
// Xdmf Smart Pointer Test

4
#include <libxml/xpointer.h>
5
#include <libxml/xmlreader.h>
6
#include <map>
7 8 9
#include "XdmfCoreItemFactory.hpp"
#include "XdmfCoreReader.hpp"
#include "XdmfItem.hpp"
10
#include "XdmfSystemUtils.hpp"
11 12 13 14 15 16 17 18

/**
 * PIMPL
 */
class XdmfCoreReader::XdmfCoreReaderImpl {

public:

19
	XdmfCoreReaderImpl(const boost::shared_ptr<const XdmfCoreItemFactory> itemFactory) :
20 21 22 23 24 25 26 27
		mItemFactory(itemFactory)
	{
	};

	~XdmfCoreReaderImpl()
	{
	};

28 29 30
	/**
	 * Constructs XdmfItems for all nodes in currNode's tree.  XdmfItems are constructed by recursively calling this function for all children of currNode.
	 */
31
	std::vector<boost::shared_ptr<XdmfItem> > read(xmlNodePtr currNode, const xmlXPathContextPtr xPathContext, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap, const std::string & xmlDir) const
32 33 34 35 36 37 38
	{
		std::vector<boost::shared_ptr<XdmfItem> > myItems;

		while(currNode != NULL)
		{
			if(currNode->type == XML_ELEMENT_NODE)
			{
39
				xmlChar * xpointer = NULL;
40
				if(xmlStrcmp(currNode->name, (xmlChar*)"include") == 0)
41
				{
42
					// Deal with proper reading of XIncludes
43 44 45 46 47 48 49 50 51
					xmlAttrPtr currAttribute = currNode->properties;
					while(currAttribute != NULL)
					{
						if(xmlStrcmp(currAttribute->name, (xmlChar*)"xpointer") == 0)
						{
							xpointer = currAttribute->children->content;
							break;
						}
					}
52
					xmlXPathObjectPtr xPathObject = xmlXPtrEval(xpointer, xPathContext);
53
					for(unsigned int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
54
					{
55
						this->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathContext, xPathMap, myItems, xmlDir);
56
					}
57
					xmlXPathFreeObject(xPathObject);
58 59 60
				}
				else
				{
61
					// Normal reading
62
					this->readSingleNode(currNode, xPathContext, xPathMap, myItems, xmlDir);
63 64
				}
			}
65 66 67 68 69 70 71 72 73 74
			currNode = currNode->next;
		}
		return myItems;
	}

private:

	/**
	 * Reads a single xmlNode into an XdmfItem object in memory.  The constructed XdmfItem is added to myItems and an entry is added mapping the xmlNodePtr to the new XdmfItem in the xPathMap.
	 */
75
	void readSingleNode(const xmlNodePtr currNode, const xmlXPathContextPtr xPathContext, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap, std::vector<boost::shared_ptr<XdmfItem> > & myItems, const std::string & xmlDir) const
76 77 78 79 80 81 82 83 84 85
	{
		std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> >::const_iterator iter = xPathMap.find(currNode);
		if(iter != xPathMap.end())
		{
			myItems.push_back(iter->second);
		}
		else
		{
			std::map<std::string, std::string> itemProperties;
			if(currNode->children != NULL)
86
			{
87
				itemProperties["Content"] = (const char *)currNode->children->content;
88
				itemProperties["XMLDir"] = xmlDir;
89
			}
90

91 92 93 94 95
			xmlAttrPtr currAttribute = currNode->properties;
			while(currAttribute != NULL)
			{
				itemProperties[(const char *)currAttribute->name] = (const char *)currAttribute->children->content;
				currAttribute = currAttribute->next;
96
			}
97
			std::vector<boost::shared_ptr<XdmfItem> > childItems = this->read(currNode->children, xPathContext, xPathMap, xmlDir);
98
			boost::shared_ptr<XdmfItem> newItem = mItemFactory->createItem((const char *)currNode->name, itemProperties);
99 100 101 102
			if(newItem == NULL)
			{
				assert(false);
			}
103 104 105
			newItem->populateItem(itemProperties, childItems);
			myItems.push_back(newItem);
			xPathMap[currNode] = newItem;
106 107 108
		}
	}

109
	const boost::shared_ptr<const XdmfCoreItemFactory> mItemFactory;
110 111
};

112
XdmfCoreReader::XdmfCoreReader(const boost::shared_ptr<const XdmfCoreItemFactory> itemFactory) :
113 114 115 116 117 118 119 120 121 122 123
	mImpl(new XdmfCoreReaderImpl(itemFactory))
{
}

XdmfCoreReader::~XdmfCoreReader()
{
	delete mImpl;
}

boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) const
{
124
	std::string xmlDir = XdmfSystemUtils::getRealPath(filePath);
125
	size_t index = xmlDir.find_last_of("/\\");
126 127
	if(index != std::string::npos)
	{
128
	    xmlDir = xmlDir.substr(0, index + 1);
129 130
	}

131 132
	const xmlDocPtr document = xmlReadFile(filePath.c_str(), NULL, 0);
	const xmlXPathContextPtr xPathContext = xmlXPtrNewContext(document, NULL, NULL);
133 134 135 136
	if(document == NULL)
	{
		assert(false);
	}
137
	const xmlNodePtr currNode = xmlDocGetRootElement(document);
138

139
	std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > xPathMap;
140
	const std::vector<boost::shared_ptr<XdmfItem> > toReturn = mImpl->read(currNode->children, xPathContext, xPathMap, xmlDir);
141
	xmlXPathFreeContext(xPathContext);
142 143 144 145 146
	xmlFreeDoc(document);
	xmlCleanupParser();

	return toReturn[0];
}