Medical Imaging Interaction Toolkit  2018.4.99-389bf124
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 #include <mitkXMLSerializable.h>
13 #include "mitkEndoDebug.h"
14 #include "mitkEndoMacros.h"
15 #include <itksys/SystemTools.hxx>
16 
17 namespace mitk
18 {
19  const std::string XMLSerializable::FILE_REFERENCE_ATTRIBUTE_NAME = "fileRef";
20  const std::string XMLSerializable::ROOT_NAME = "data";
21 
22  void mitk::XMLSerializable::ToXMLFile(const std::string& file
23  , const std::string& elemName)
24  {
25  TiXmlElement * rootElem=nullptr;
26  TiXmlElement * element=nullptr;
27 
28  // determine element to write to
29  std::string elementName = elemName;
30  if(elementName.empty())
31  elementName = this->GetNameOfClass();
32 
33  TiXmlDocument doc( file.c_str() );
34  bool loadOkay = doc.LoadFile();
35  // if the document already exists ...
36  if(loadOkay)
37  {
38  // try to identify the XML element of this class as the root
39  // or as the child of the root
40  rootElem = doc.RootElement();
41  endoAssertMsg( rootElem, "No root element found in " << file );
42 
43  // if root element represents this element remove the root
44  if( rootElem->ValueStr() == elementName )
45  {
46  doc.RemoveChild(rootElem);
47  rootElem = nullptr;
48  }
49  else
50  {
51  // if it is a child of the root remove it too
52  element = rootElem->FirstChildElement(elementName);
53  if(element)
54  rootElem->RemoveChild(element);
55  }
56  }
57  else
58  {
59  // document did not exist, create new one with declration
60  auto decl = new TiXmlDeclaration( "1.0", "", "" );
61  doc.LinkEndChild( decl );
62  }
63 
64  m_XMLFileName = file;
65 
66  // create element (if the document already exists this element was removed)
67  element = new TiXmlElement( elementName );
68  this->ToXML( element );
69 
70  // if we do not have a root element create a new one
71  if(!rootElem)
72  rootElem = new TiXmlElement( ROOT_NAME );
73  // add the element node as child
74  rootElem->LinkEndChild(element);
75 
76  // if no root element exists, add it now
77  if(doc.RootElement() == nullptr)
78  doc.LinkEndChild( rootElem );
79 
80  if(!doc.SaveFile( file ))
81  {
82  std::ostringstream s; s << "File " << file
83  << " could not be written. Please check permissions.";
84  throw std::logic_error(s.str());
85  }
86  }
87 
89  {
90  return m_XMLFileName;
91  }
92 
93  void mitk::XMLSerializable::FromXMLFile(const std::string& file
94  , const std::string& elemName)
95  {
96  endodebug( "Trying to read from " << file )
97 
98  TiXmlDocument doc( file.c_str() );
99  bool loadOkay = doc.LoadFile();
100  if(!loadOkay)
101  {
102  std::ostringstream s; s << "File " << file
103  << " could not be loaded!";
104  throw std::logic_error(s.str().c_str());
105  }
106 
107  m_XMLFileName = file;
108 
109  TiXmlElement* elem = doc.FirstChildElement();
110  endoAssertMsg( elem, "No root element found" );
111 
112  // determine element to read from
113  std::string elementName = elemName;
114  if(elementName.empty())
115  elementName = this->GetNameOfClass();
116  // try again with the first element
117  if(strcmp(elem->Value(), elementName.c_str()) != 0)
118  elem = elem->FirstChildElement(elementName.c_str());
119 
120  endoAssertMsg( elem, "No child element \"" << elementName <<
121  "\" found in " << file );
122 
123  // if theres an attribute as file reference try to load the class
124  // from that file
125  std::string filename;
126  if(elem->QueryStringAttribute(FILE_REFERENCE_ATTRIBUTE_NAME.c_str(), &filename)
127  == TIXML_SUCCESS)
128  {
129  if( !itksys::SystemTools::FileIsFullPath(filename.c_str()) )
130  filename = itksys::SystemTools::GetFilenamePath(file) + "/" + filename;
131  this->FromXMLFile(filename);
132  return; // exit!
133  }
134 
135  this->FromXML( elem );
136  }
137 }
std::string GetXMLFileName() const
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)
static const std::string FILE_REFERENCE_ATTRIBUTE_NAME
virtual void ToXMLFile(const std::string &file, const std::string &elemName="")