1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkXMLTreeReader.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16 Copyright 2008 Sandia Corporation.
17 Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18 the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20
21 #include "vtkXMLTreeReader.h"
22
23 #include "vtkBitArray.h"
24 #include "vtkInformation.h"
25 #include "vtkIdTypeArray.h"
26 #include "vtkMutableDirectedGraph.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPointData.h"
29 #include "vtkSmartPointer.h"
30 #include "vtkStringArray.h"
31 #include "vtkTree.h"
32
33 #include "vtk_libxml2.h"
34 #include VTKLIBXML2_HEADER(parser.h)
35 #include VTKLIBXML2_HEADER(tree.h)
36
37 vtkStandardNewMacro(vtkXMLTreeReader);
38
39 const char * vtkXMLTreeReader::TagNameField = ".tagname";
40 const char * vtkXMLTreeReader::CharDataField = ".chardata";
41
vtkXMLTreeReader()42 vtkXMLTreeReader::vtkXMLTreeReader()
43 {
44 this->FileName = 0;
45 this->XMLString = 0;
46 this->SetNumberOfInputPorts(0);
47 this->SetNumberOfOutputPorts(1);
48 this->ReadCharData = 0;
49 this->ReadTagName = 1;
50 this->MaskArrays = 0;
51 this->EdgePedigreeIdArrayName = 0;
52 this->SetEdgePedigreeIdArrayName("edge id");
53 this->VertexPedigreeIdArrayName = 0;
54 this->SetVertexPedigreeIdArrayName("vertex id");
55 this->GenerateEdgePedigreeIds = true;
56 this->GenerateVertexPedigreeIds = true;
57 }
58
~vtkXMLTreeReader()59 vtkXMLTreeReader::~vtkXMLTreeReader()
60 {
61 this->SetFileName(0);
62 this->SetXMLString(0);
63 this->SetEdgePedigreeIdArrayName(0);
64 this->SetVertexPedigreeIdArrayName(0);
65 }
66
PrintSelf(ostream & os,vtkIndent indent)67 void vtkXMLTreeReader::PrintSelf(ostream& os, vtkIndent indent)
68 {
69 this->Superclass::PrintSelf(os, indent);
70 os << indent << "FileName: "
71 << (this->FileName ? this->FileName : "(none)") << endl;
72 os << indent << "ReadCharData: "
73 << (this->ReadCharData ? "on" : "off") << endl;
74 os << indent << "ReadTagName: "
75 << (this->ReadTagName ? "on" : "off") << endl;
76 os << indent << "MaskArrays: "
77 << (this->MaskArrays ? "on" : "off") << endl;
78 os << indent << "XMLString: "
79 << (this->XMLString ? this->XMLString : "(none)") << endl;
80 os << indent << "EdgePedigreeIdArrayName: "
81 << (this->EdgePedigreeIdArrayName ? this->EdgePedigreeIdArrayName : "(null)") << endl;
82 os << indent << "VertexPedigreeIdArrayName: "
83 << (this->VertexPedigreeIdArrayName ? this->VertexPedigreeIdArrayName : "(null)") << endl;
84 os << indent << "GenerateEdgePedigreeIds: "
85 << (this->GenerateEdgePedigreeIds ? "on" : "off") << endl;
86 os << indent << "GenerateVertexPedigreeIds: "
87 << (this->GenerateVertexPedigreeIds ? "on" : "off") << endl;
88 }
89
vtkXMLTreeReaderProcessElement(vtkMutableDirectedGraph * tree,vtkIdType parent,xmlNode * node,int readCharData,int maskArrays)90 static void vtkXMLTreeReaderProcessElement(vtkMutableDirectedGraph *tree,
91 vtkIdType parent, xmlNode *node, int readCharData, int maskArrays)
92 {
93 vtkDataSetAttributes *data = tree->GetVertexData();
94 vtkStringArray *nameArr = vtkStringArray::SafeDownCast(data->GetAbstractArray(vtkXMLTreeReader::TagNameField));
95 vtkStdString content;
96 for (xmlNode *curNode = node; curNode; curNode = curNode->next)
97 {
98 //cerr << "type=" << curNode->type << ",name=" << curNode->name << endl;
99 if (curNode->content)
100 {
101 const char *curContent = reinterpret_cast<const char*>(curNode->content);
102 content += curContent;
103 //cerr << "content=" << curNode->content << endl;
104 }
105
106 if (curNode->type != XML_ELEMENT_NODE)
107 {
108 continue;
109 }
110
111 vtkIdType vertex = -1;
112 vertex = tree->AddVertex();
113 if (parent != -1)
114 {
115 tree->AddEdge(parent, vertex);
116 }
117
118 // Append the node tag and character data to the vtkPointData
119 if (nameArr) // If the reader has ReadTagName = ON then populate this array
120 {
121 nameArr->InsertValue(vertex, reinterpret_cast<const char*>(curNode->name));
122 }
123
124 // Append the element attributes to the vtkPointData
125 for (xmlAttr *curAttr = curNode->properties; curAttr; curAttr = curAttr->next)
126 {
127 const char *name = reinterpret_cast<const char*>(curAttr->name);
128 int len = static_cast<int>(strlen(name));
129 char *validName = new char[len+8];
130 strcpy(validName, ".valid.");
131 strcat(validName, name);
132 vtkStringArray *stringArr = vtkStringArray::SafeDownCast(data->GetAbstractArray(name));
133 vtkBitArray *bitArr = 0;
134 if (maskArrays)
135 {
136 bitArr = vtkBitArray::SafeDownCast(data->GetAbstractArray(validName));
137 }
138 if (!stringArr)
139 {
140 stringArr = vtkStringArray::New();
141 stringArr->SetName(name);
142 data->AddArray(stringArr);
143 stringArr->Delete();
144 if (maskArrays)
145 {
146 bitArr = vtkBitArray::New();
147 bitArr->SetName(validName);
148 data->AddArray(bitArr);
149 bitArr->Delete();
150 }
151 }
152 const char *value = reinterpret_cast<const char*>(curAttr->children->content);
153 stringArr->InsertValue(vertex, value);
154 if (maskArrays)
155 {
156 for (vtkIdType i = bitArr->GetNumberOfTuples(); i < vertex; i++)
157 {
158 bitArr->InsertNextValue(false);
159 }
160 bitArr->InsertNextValue(true);
161 }
162 //cerr << "attname=" << name << ",value=" << value << endl;
163 delete [] validName;
164 }
165
166 // Process this node's children
167 vtkXMLTreeReaderProcessElement(tree, vertex, curNode->children, readCharData, maskArrays);
168 }
169
170 if (readCharData && parent >= 0)
171 {
172 vtkStringArray *charArr = vtkStringArray::SafeDownCast(data->GetAbstractArray(vtkXMLTreeReader::CharDataField));
173 charArr->InsertValue(parent, content);
174 }
175 }
176
RequestData(vtkInformation *,vtkInformationVector **,vtkInformationVector * outputVector)177 int vtkXMLTreeReader::RequestData(
178 vtkInformation*,
179 vtkInformationVector**,
180 vtkInformationVector *outputVector)
181 {
182 if (!this->FileName && !this->XMLString)
183 {
184 vtkErrorMacro("A FileName or XMLString must be specified");
185 return 0;
186 }
187
188 xmlDoc *doc = NULL;
189 if (this->FileName)
190 {
191 // Parse the file and get the DOM
192 doc = xmlReadFile(this->FileName, NULL, 0);
193 }
194 else if (this->XMLString)
195 {
196 // Parse from memory and get the DOM
197 doc = xmlReadMemory(this->XMLString, static_cast<int>(strlen(this->XMLString)), "noname.xml", NULL, 0);
198 }
199
200 // Store the XML hierarchy into a vtkMutableDirectedGraph,
201 // later to be placed in a vtkTree.
202 vtkSmartPointer<vtkMutableDirectedGraph> builder =
203 vtkSmartPointer<vtkMutableDirectedGraph>::New();
204
205 vtkDataSetAttributes *data = builder->GetVertexData();
206
207 if (this->ReadTagName)
208 {
209 vtkStringArray *nameArr = vtkStringArray::New();
210 nameArr->SetName(vtkXMLTreeReader::TagNameField);
211 data->AddArray(nameArr);
212 nameArr->Delete();
213 }
214
215 if (this->ReadCharData)
216 {
217 vtkStringArray *charArr = vtkStringArray::New();
218 charArr->SetName(vtkXMLTreeReader::CharDataField);
219 data->AddArray(charArr);
220 charArr->Delete();
221 }
222
223 // Get the root element node
224 xmlNode *rootElement = xmlDocGetRootElement(doc);
225 vtkXMLTreeReaderProcessElement(builder, -1, rootElement, this->ReadCharData, this->MaskArrays);
226
227 xmlFreeDoc(doc);
228
229 // Make all the arrays the same size
230 for (int i = 0; i < data->GetNumberOfArrays(); i++)
231 {
232 vtkStringArray *stringArr = vtkStringArray::SafeDownCast(data->GetAbstractArray(i));
233 if (stringArr && (stringArr->GetNumberOfTuples() < builder->GetNumberOfVertices()))
234 {
235 stringArr->InsertValue(builder->GetNumberOfVertices() - 1, vtkStdString(""));
236 }
237 }
238
239 // Move the XML hierarchy into a vtkTree
240 vtkTree *output = vtkTree::GetData(outputVector);
241 if (!output->CheckedShallowCopy(builder))
242 {
243 vtkErrorMacro(<<"Structure is not a valid tree!");
244 return 0;
245 }
246
247 // Look for or generate vertex pedigree id array.
248 if (this->GenerateVertexPedigreeIds)
249 {
250 // Create vertex pedigree ids
251 vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New();
252 ids->SetName(this->VertexPedigreeIdArrayName);
253 vtkIdType numVerts = output->GetNumberOfVertices();
254 ids->SetNumberOfTuples(numVerts);
255 for (vtkIdType i = 0; i < numVerts; ++i)
256 {
257 ids->SetValue(i, i);
258 }
259 output->GetVertexData()->SetPedigreeIds(ids);
260 }
261 else
262 {
263 vtkAbstractArray* pedIds = output->GetVertexData()->GetAbstractArray(this->VertexPedigreeIdArrayName);
264 if (pedIds)
265 {
266 output->GetVertexData()->SetPedigreeIds(pedIds);
267 }
268 else
269 {
270 vtkErrorMacro(<< "Vertex pedigree ID array not found.");
271 return 0;
272 }
273 }
274
275 // Look for or generate edge pedigree id array.
276 if (this->GenerateEdgePedigreeIds)
277 {
278 // Create vertex pedigree ids
279 vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New();
280 ids->SetName(this->EdgePedigreeIdArrayName);
281 vtkIdType numEdges = output->GetNumberOfEdges();
282 ids->SetNumberOfTuples(numEdges);
283 for (vtkIdType i = 0; i < numEdges; ++i)
284 {
285 ids->SetValue(i, i);
286 }
287 output->GetEdgeData()->SetPedigreeIds(ids);
288 }
289 else
290 {
291 vtkAbstractArray* pedIds = output->GetEdgeData()->GetAbstractArray(this->EdgePedigreeIdArrayName);
292 if (pedIds)
293 {
294 output->GetEdgeData()->SetPedigreeIds(pedIds);
295 }
296 else
297 {
298 vtkErrorMacro(<< "Edge pedigree ID array not found.");
299 return 0;
300 }
301 }
302
303 return 1;
304 }
305
306