XdmfCoreReader.cpp 4.88 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
	void closeFile()
	{
		xmlXPathFreeContext(mXPathContext);
		xmlFreeDoc(mDocument);
		xmlCleanupParser();
	}

	void openFile(const std::string & filePath)
	{
		mXMLDir = XdmfSystemUtils::getRealPath(filePath);
		size_t index = mXMLDir.find_last_of("/\\");
		if(index != std::string::npos)
		{
		    mXMLDir = mXMLDir.substr(0, index + 1);
		}

		mDocument = xmlReadFile(filePath.c_str(), NULL, 0);

		if(mDocument == NULL)
		{
			assert(false);
		}

		mXPathContext = xmlXPtrNewContext(mDocument, NULL, NULL);
	}

54 55 56
	/**
	 * Constructs XdmfItems for all nodes in currNode's tree.  XdmfItems are constructed by recursively calling this function for all children of currNode.
	 */
57
	std::vector<boost::shared_ptr<XdmfItem> > read(xmlNodePtr currNode, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap) const
58 59 60 61 62 63 64
	{
		std::vector<boost::shared_ptr<XdmfItem> > myItems;

		while(currNode != NULL)
		{
			if(currNode->type == XML_ELEMENT_NODE)
			{
65
				xmlChar * xpointer = NULL;
66
				if(xmlStrcmp(currNode->name, (xmlChar*)"include") == 0)
67
				{
68
					// Deal with proper reading of XIncludes
69 70 71 72 73 74 75 76 77
					xmlAttrPtr currAttribute = currNode->properties;
					while(currAttribute != NULL)
					{
						if(xmlStrcmp(currAttribute->name, (xmlChar*)"xpointer") == 0)
						{
							xpointer = currAttribute->children->content;
							break;
						}
					}
78
					xmlXPathObjectPtr xPathObject = xmlXPtrEval(xpointer, mXPathContext);
79
					for(unsigned int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
80
					{
81
						this->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathMap, myItems);
82
					}
83
					xmlXPathFreeObject(xPathObject);
84 85 86
				}
				else
				{
87
					// Normal reading
88
					this->readSingleNode(currNode, xPathMap, myItems);
89 90
				}
			}
91 92 93 94 95 96 97 98
			currNode = currNode->next;
		}
		return myItems;
	}

	/**
	 * 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.
	 */
99
	void readSingleNode(const xmlNodePtr currNode, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap, std::vector<boost::shared_ptr<XdmfItem> > & myItems) const
100 101 102 103 104 105 106 107 108 109
	{
		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)
110
			{
111
				itemProperties["Content"] = (const char *)currNode->children->content;
112
				itemProperties["XMLDir"] = mXMLDir;
113
			}
114

115 116 117 118 119
			xmlAttrPtr currAttribute = currNode->properties;
			while(currAttribute != NULL)
			{
				itemProperties[(const char *)currAttribute->name] = (const char *)currAttribute->children->content;
				currAttribute = currAttribute->next;
120
			}
121
			std::vector<boost::shared_ptr<XdmfItem> > childItems = this->read(currNode->children, xPathMap);
122
			boost::shared_ptr<XdmfItem> newItem = mItemFactory->createItem((const char *)currNode->name, itemProperties);
123 124 125 126
			if(newItem == NULL)
			{
				assert(false);
			}
127 128 129
			newItem->populateItem(itemProperties, childItems);
			myItems.push_back(newItem);
			xPathMap[currNode] = newItem;
130 131 132
		}
	}

133
	xmlDocPtr mDocument;
134
	const boost::shared_ptr<const XdmfCoreItemFactory> mItemFactory;
135 136
	std::string mXMLDir;
	xmlXPathContextPtr mXPathContext;
137 138
};

139
XdmfCoreReader::XdmfCoreReader(const boost::shared_ptr<const XdmfCoreItemFactory> itemFactory) :
140 141 142 143 144 145 146 147 148 149 150
	mImpl(new XdmfCoreReaderImpl(itemFactory))
{
}

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

boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) const
{
151 152
	mImpl->openFile(filePath);
	const xmlNodePtr currNode = xmlDocGetRootElement(mImpl->mDocument);
153
	std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > xPathMap;
154 155
	const std::vector<boost::shared_ptr<XdmfItem> > toReturn = mImpl->read(currNode->children, xPathMap);
	mImpl->closeFile();
156 157
	return toReturn[0];
}
158 159 160

std::vector<boost::shared_ptr<XdmfItem> > XdmfCoreReader::read(const std::string & filePath, const std::string & xPath) const
{
161
	mImpl->openFile(filePath);
162 163
	std::vector<boost::shared_ptr<XdmfItem> > toReturn;
	std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > xPathMap;
164
	xmlXPathObjectPtr xPathObject = xmlXPathEvalExpression((xmlChar*)xPath.c_str(), mImpl->mXPathContext);
165 166
	for(unsigned int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
	{
167
		mImpl->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathMap, toReturn);
168 169
	}
	xmlXPathFreeObject(xPathObject);
170
	mImpl->closeFile();
171 172
	return toReturn;
}