Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkXMLSerializable.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 #include <mitkXMLSerializable.h>
17 #include "mitkEndoDebug.h"
18 #include "mitkEndoMacros.h"
19 #include <itksys/SystemTools.hxx>
20 
21 namespace mitk
22 {
23  const std::string XMLSerializable::FILE_REFERENCE_ATTRIBUTE_NAME = "fileRef";
24  const std::string XMLSerializable::ROOT_NAME = "data";
25 
26  void mitk::XMLSerializable::ToXMLFile(const std::string& file
27  , const std::string& elemName)
28  {
29  TiXmlElement * rootElem=nullptr;
30  TiXmlElement * element=nullptr;
31 
32  // determine element to write to
33  std::string elementName = elemName;
34  if(elementName.empty())
35  elementName = this->GetNameOfClass();
36 
37  TiXmlDocument doc( file.c_str() );
38  bool loadOkay = doc.LoadFile();
39  // if the document already exists ...
40  if(loadOkay)
41  {
42  // try to identify the XML element of this class as the root
43  // or as the child of the root
44  rootElem = doc.RootElement();
45  endoAssertMsg( rootElem, "No root element found in " << file );
46 
47  // if root element represents this element remove the root
48  if( rootElem->ValueStr() == elementName )
49  {
50  doc.RemoveChild(rootElem);
51  rootElem = nullptr;
52  }
53  else
54  {
55  // if it is a child of the root remove it too
56  element = rootElem->FirstChildElement(elementName);
57  if(element)
58  rootElem->RemoveChild(element);
59  }
60  }
61  else
62  {
63  // document did not exist, create new one with declration
64  auto decl = new TiXmlDeclaration( "1.0", "", "" );
65  doc.LinkEndChild( decl );
66  }
67 
68  m_XMLFileName = file;
69 
70  // create element (if the document already exists this element was removed)
71  element = new TiXmlElement( elementName );
72  this->ToXML( element );
73 
74  // if we do not have a root element create a new one
75  if(!rootElem)
76  rootElem = new TiXmlElement( ROOT_NAME );
77  // add the element node as child
78  rootElem->LinkEndChild(element);
79 
80  // if no root element exists, add it now
81  if(doc.RootElement() == nullptr)
82  doc.LinkEndChild( rootElem );
83 
84  if(!doc.SaveFile( file ))
85  {
86  std::ostringstream s; s << "File " << file
87  << " could not be written. Please check permissions.";
88  throw std::logic_error(s.str());
89  }
90  }
91 
93  {
94  return m_XMLFileName;
95  }
96 
97  void mitk::XMLSerializable::FromXMLFile(const std::string& file
98  , const std::string& elemName)
99  {
100  endodebug( "Trying to read from " << file )
101 
102  TiXmlDocument doc( file.c_str() );
103  bool loadOkay = doc.LoadFile();
104  if(!loadOkay)
105  {
106  std::ostringstream s; s << "File " << file
107  << " could not be loaded!";
108  throw std::logic_error(s.str().c_str());
109  }
110 
111  m_XMLFileName = file;
112 
113  TiXmlElement* elem = doc.FirstChildElement();
114  endoAssertMsg( elem, "No root element found" );
115 
116  // determine element to read from
117  std::string elementName = elemName;
118  if(elementName.empty())
119  elementName = this->GetNameOfClass();
120  // try again with the first element
121  if(strcmp(elem->Value(), elementName.c_str()) != 0)
122  elem = elem->FirstChildElement(elementName.c_str());
123 
124  endoAssertMsg( elem, "No child element \"" << elementName <<
125  "\" found in " << file );
126 
127  // if theres an attribute as file reference try to load the class
128  // from that file
129  std::string filename;
130  if(elem->QueryStringAttribute(FILE_REFERENCE_ATTRIBUTE_NAME.c_str(), &filename)
131  == TIXML_SUCCESS)
132  {
133  if( !itksys::SystemTools::FileIsFullPath(filename.c_str()) )
134  filename = itksys::SystemTools::GetFilenamePath(file) + "/" + filename;
135  this->FromXMLFile(filename);
136  return; // exit!
137  }
138 
139  this->FromXML( elem );
140  }
141 }
virtual void FromXMLFile(const std::string &file, const std::string &elemName="")
#define endoAssertMsg(a, msg)
DataCollection - Class to facilitate loading/accessing structured data.
static const std::string ROOT_NAME
#define endodebug(msg)
std::string GetXMLFileName() const
static const std::string filename
static const std::string FILE_REFERENCE_ATTRIBUTE_NAME
virtual void ToXMLFile(const std::string &file, const std::string &elemName="")