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

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

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

public:

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

	~XdmfCoreReaderImpl()
	{
	};

26 27 28
	/**
	 * Constructs XdmfItems for all nodes in currNode's tree.  XdmfItems are constructed by recursively calling this function for all children of currNode.
	 */
29
	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
30 31 32 33 34 35 36
	{
		std::vector<boost::shared_ptr<XdmfItem> > myItems;

		while(currNode != NULL)
		{
			if(currNode->type == XML_ELEMENT_NODE)
			{
37
				xmlChar * xpointer = NULL;
38
				if(xmlStrcmp(currNode->name, (xmlChar*)"include") == 0)
39
				{
40
					// Deal with proper reading of XIncludes
41 42 43 44 45 46 47 48 49
					xmlAttrPtr currAttribute = currNode->properties;
					while(currAttribute != NULL)
					{
						if(xmlStrcmp(currAttribute->name, (xmlChar*)"xpointer") == 0)
						{
							xpointer = currAttribute->children->content;
							break;
						}
					}
50
					xmlXPathObjectPtr xPathObject = xmlXPtrEval(xpointer, xPathContext);
51
					for(unsigned int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
52
					{
53
						this->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathContext, xPathMap, myItems, xmlDir);
54
					}
55
					xmlXPathFreeObject(xPathObject);
56 57 58
				}
				else
				{
59
					// Normal reading
60
					this->readSingleNode(currNode, xPathContext, xPathMap, myItems, xmlDir);
61 62
				}
			}
63 64 65 66 67 68 69 70 71 72
			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.
	 */
73
	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
74 75 76 77 78 79 80 81 82 83
	{
		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)
84
			{
85
				itemProperties["Content"] = (const char *)currNode->children->content;
86
				itemProperties["XMLDir"] = xmlDir;
87
			}
88

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

107
	const boost::shared_ptr<const XdmfCoreItemFactory> mItemFactory;
108 109
};

110
XdmfCoreReader::XdmfCoreReader(const boost::shared_ptr<const XdmfCoreItemFactory> itemFactory) :
111 112 113 114 115 116 117 118 119 120 121 122 123
	mImpl(new XdmfCoreReaderImpl(itemFactory))
{
	std::cout << "Created XdmfReader " << this << std::endl;
}

XdmfCoreReader::~XdmfCoreReader()
{
	delete mImpl;
	std::cout << "Deleted XdmfReader " << this << std::endl;
}

boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) const
{
124 125
	std::string xmlDir = XdmfObject::getRealPath(filePath);
	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];
}