Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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="")