Commit 60362c29 authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Add XPath writing capabilities to XdmfWriter. Whenever a duplicate...

ENH: Add XPath writing capabilities to XdmfWriter.  Whenever a duplicate XdmfItem is written to disk, instead of writing it twice, XPath the first.  We will hopefully mirror this behavior when reading in.
parent 1987ebf9
......@@ -2,6 +2,7 @@
// Xdmf Smart Pointer Test
#include <libxml/tree.h>
#include <map>
#include <sstream>
#include "XdmfArray.hpp"
#include "XdmfItem.hpp"
......@@ -20,22 +21,44 @@ public:
mHDF5Writer(hdf5Writer),
mLightDataLimit(100),
mMode(Default),
mTraverseLevel(0),
mXMLCurrentNode(NULL),
mXMLDocument(NULL),
mXMLFilePath(xmlFilePath)
mXMLFilePath(xmlFilePath),
mXPathCount(0),
mXPathString("")
{
};
~XdmfWriterImpl()
{
};
void closeFile()
{
mXPath.clear();
xmlSaveFormatFile(mXMLFilePath.c_str(), mXMLDocument, 1);
xmlFreeDoc(mXMLDocument);
xmlCleanupParser();
};
void openFile()
{
mXMLDocument = xmlNewDoc((xmlChar*)"1.0");
mXMLCurrentNode = xmlNewNode(NULL, (xmlChar*)"Xdmf");
xmlNewProp(mXMLCurrentNode, (xmlChar*)"xmlns:xi", (xmlChar*)"http://www.w3.org/2001/XInclude");
xmlNewProp(mXMLCurrentNode, (xmlChar*)"Version", (xmlChar*)"2.0");
xmlDocSetRootElement(mXMLDocument, mXMLCurrentNode);
}
boost::shared_ptr<XdmfHDF5Writer> mHDF5Writer;
unsigned int mLightDataLimit;
Mode mMode;
unsigned int mTraverseLevel;
xmlNodePtr mXMLCurrentNode;
xmlDocPtr mXMLDocument;
std::string mXMLFilePath;
std::map<const XdmfItem * const, std::string> mXPath;
unsigned int mXPathCount;
std::string mXPathString;
};
XdmfWriter::XdmfWriter(const std::string & xmlFilePath)
......@@ -67,13 +90,6 @@ XdmfWriter::~XdmfWriter()
std::cout << "Deleted XdmfWriter " << this << std::endl;
}
void XdmfWriter::closeFile()
{
xmlSaveFormatFile(mImpl->mXMLFilePath.c_str(), mImpl->mXMLDocument, 1);
xmlFreeDoc(mImpl->mXMLDocument);
xmlCleanupParser();
}
boost::shared_ptr<XdmfHDF5Writer> XdmfWriter::getHDF5Writer()
{
return boost::const_pointer_cast<XdmfHDF5Writer>(static_cast<const XdmfWriter &>(*this).getHDF5Writer());
......@@ -99,13 +115,6 @@ XdmfWriter::Mode XdmfWriter::getMode() const
return mImpl->mMode;
}
void XdmfWriter::openFile()
{
mImpl->mXMLDocument = xmlNewDoc((xmlChar*)"1.0");
mImpl->mXMLCurrentNode = xmlNewNode(NULL, (xmlChar*)"Xdmf");
xmlDocSetRootElement(mImpl->mXMLDocument, mImpl->mXMLCurrentNode);
}
void XdmfWriter::setLightDataLimit(const unsigned int numValues)
{
mImpl->mLightDataLimit = numValues;
......@@ -141,23 +150,50 @@ void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisito
void XdmfWriter::visit(XdmfItem & item, const boost::shared_ptr<XdmfBaseVisitor> visitor)
{
if(mImpl->mTraverseLevel == 0)
if(mImpl->mXPathString.compare("") == 0)
{
this->openFile();
mImpl->openFile();
}
mImpl->mTraverseLevel++;
mImpl->mXPathCount++;
xmlNodePtr parentNode = mImpl->mXMLCurrentNode;
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)item.getItemTag().c_str(), NULL);
const std::map<std::string, std::string> itemProperties = item.getItemProperties();
for(std::map<std::string, std::string>::const_iterator iter = itemProperties.begin(); iter != itemProperties.end(); ++iter)
std::string parentXPathString = mImpl->mXPathString;
std::stringstream newXPathString;
newXPathString << mImpl->mXPathString << "/" << mImpl->mXPathCount;
mImpl->mXPathString = newXPathString.str();
std::map<const XdmfItem * const, std::string>::const_iterator iter = mImpl->mXPath.find(&item);
if(iter != mImpl->mXPath.end())
{
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)iter->first.c_str(), (xmlChar*)iter->second.c_str());
// Inserted before --- just xpath location of previously written node
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)"xi:include", NULL);
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)"xpointer", (xmlChar*)iter->second.c_str());
}
item.traverse(visitor);
else
{
// Not inserted before --- need to write all data and traverse.
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)item.getItemTag().c_str(), NULL);
std::stringstream xPathProp;
xPathProp << "element(/1" << mImpl->mXPathString << ")";
mImpl->mXPath[&item] = xPathProp.str();
const std::map<std::string, std::string> itemProperties = item.getItemProperties();
for(std::map<std::string, std::string>::const_iterator iter = itemProperties.begin(); iter != itemProperties.end(); ++iter)
{
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)iter->first.c_str(), (xmlChar*)iter->second.c_str());
}
unsigned int parentCount = mImpl->mXPathCount;
mImpl->mXPathCount = 0;
item.traverse(visitor);
mImpl->mXPathCount = parentCount;
}
mImpl->mXMLCurrentNode = parentNode;
mImpl->mTraverseLevel--;
if(mImpl->mTraverseLevel == 0)
mImpl->mXPathString = parentXPathString;
if(mImpl->mXPathString.compare("") == 0)
{
this->closeFile();
mImpl->closeFile();
}
}
......@@ -141,9 +141,6 @@ private:
XdmfWriter(const XdmfWriter & writer); // Not implemented.
void operator=(const XdmfWriter & writer); // Not implemented.
void closeFile();
void openFile();
XdmfWriterImpl * mImpl;
};
......
......@@ -10,6 +10,7 @@ set(XdmfCxxTests
TestXdmfVisitorValueCounter
TestXdmfWriter
TestXdmfWriterHDF5ThenXML
TestXdmfXPath
)
foreach(test ${XdmfCxxTests})
......
#include <fstream>
#include <sstream>
#include "XdmfItem.hpp"
#include "XdmfDomain.hpp"
#include "XdmfReader.hpp"
#include "XdmfWriter.hpp"
......
#include "XdmfDomain.hpp"
#include "XdmfWriter.hpp"
#include "XdmfTestDataGenerator.hpp"
......
#include "XdmfDomain.hpp"
#include "XdmfHDF5Writer.hpp"
#include "XdmfWriter.hpp"
......
#include <fstream>
#include <sstream>
#include "XdmfDomain.hpp"
#include "XdmfWriter.hpp"
#include "XdmfTestDataGenerator.hpp"
int main(int argc, char* argv[])
{
boost::shared_ptr<XdmfWriter> writer = XdmfWriter::New("xpath.xmf");
boost::shared_ptr<XdmfGrid> grid = XdmfTestDataGenerator::createHexahedron();
boost::shared_ptr<XdmfGrid> newGrid = XdmfGrid::New();
newGrid->setName("NoAttributes");
newGrid->setGeometry(grid->getGeometry());
newGrid->setTopology(grid->getTopology());
boost::shared_ptr<XdmfDomain> domain = XdmfDomain::New();
domain->insert(grid);
domain->insert(grid);
domain->insert(newGrid);
domain->accept(writer);
// Try to find xpaths written to file
std::ifstream file("xpath.xmf");
std::stringstream fileBuffer;
fileBuffer << file.rdbuf();
std::string fileContents(fileBuffer.str());
assert(fileContents.find("xpointer=\"element(/1/1/1)\"") != std::string::npos);
assert(fileContents.find("xpointer=\"element(/1/1/1/2)\"") != std::string::npos);
assert(fileContents.find("xpointer=\"element(/1/1/1/3)\"") != std::string::npos);
return 0;
}
......@@ -2,7 +2,6 @@
#include "XdmfAttributeCenter.hpp"
#include "XdmfAttributeType.hpp"
#include "XdmfArray.hpp"
#include "XdmfDomain.hpp"
#include "XdmfGeometry.hpp"
#include "XdmfGeometryType.hpp"
#include "XdmfGrid.hpp"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment