Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <cassert>
23 : #include <cstddef>
24 : #include <set>
25 :
26 : #include "com/sun/star/uno/Any.hxx"
27 : #include "com/sun/star/uno/Reference.hxx"
28 : #include "com/sun/star/uno/RuntimeException.hpp"
29 : #include "com/sun/star/uno/XInterface.hpp"
30 : #include "rtl/ref.hxx"
31 : #include "rtl/strbuf.hxx"
32 : #include "rtl/string.hxx"
33 : #include "rtl/ustring.hxx"
34 : #include "xmlreader/span.hxx"
35 : #include "xmlreader/xmlreader.hxx"
36 :
37 : #include "data.hxx"
38 : #include "localizedpropertynode.hxx"
39 : #include "groupnode.hxx"
40 : #include "node.hxx"
41 : #include "nodemap.hxx"
42 : #include "parsemanager.hxx"
43 : #include "propertynode.hxx"
44 : #include "setnode.hxx"
45 : #include "xcsparser.hxx"
46 : #include "xmldata.hxx"
47 :
48 : namespace configmgr {
49 :
50 : namespace {
51 :
52 : // Conservatively merge a template or component (and its recursive parts) into
53 : // an existing instance:
54 0 : void merge(
55 : rtl::Reference< Node > const & original,
56 : rtl::Reference< Node > const & update)
57 : {
58 : assert(
59 : original.is() && update.is() && original->kind() == update->kind() &&
60 : update->getFinalized() == Data::NO_LAYER);
61 0 : if (update->getLayer() >= original->getLayer() &&
62 0 : update->getLayer() <= original->getFinalized())
63 : {
64 0 : switch (original->kind()) {
65 : case Node::KIND_PROPERTY:
66 : case Node::KIND_LOCALIZED_PROPERTY:
67 : case Node::KIND_LOCALIZED_VALUE:
68 0 : break; //TODO: merge certain parts?
69 : case Node::KIND_GROUP:
70 0 : for (NodeMap::const_iterator i2(update->getMembers().begin());
71 0 : i2 != update->getMembers().end(); ++i2)
72 : {
73 0 : NodeMap & members = original->getMembers();
74 0 : NodeMap::iterator i1(members.find(i2->first));
75 0 : if (i1 == members.end()) {
76 0 : if (i2->second->kind() == Node::KIND_PROPERTY &&
77 : static_cast< GroupNode * >(
78 0 : original.get())->isExtensible())
79 : {
80 0 : members.insert(*i2);
81 : }
82 0 : } else if (i2->second->kind() == i1->second->kind()) {
83 0 : merge(i1->second, i2->second);
84 : }
85 : }
86 0 : break;
87 : case Node::KIND_SET:
88 0 : for (NodeMap::const_iterator i2(update->getMembers().begin());
89 0 : i2 != update->getMembers().end(); ++i2)
90 : {
91 0 : NodeMap & members = original->getMembers();
92 0 : NodeMap::iterator i1(members.find(i2->first));
93 0 : if (i1 == members.end()) {
94 0 : if (static_cast< SetNode * >(original.get())->
95 0 : isValidTemplate(i2->second->getTemplateName()))
96 : {
97 0 : members.insert(*i2);
98 : }
99 0 : } else if (i2->second->kind() == i1->second->kind() &&
100 0 : (i2->second->getTemplateName() ==
101 0 : i1->second->getTemplateName()))
102 : {
103 0 : merge(i1->second, i2->second);
104 : }
105 : }
106 0 : break;
107 : case Node::KIND_ROOT:
108 : assert(false); // this cannot happen
109 0 : break;
110 : }
111 : }
112 0 : }
113 :
114 : }
115 :
116 17640 : XcsParser::XcsParser(int layer, Data & data):
117 17640 : valueParser_(layer), data_(data), state_(STATE_START), ignoring_()
118 17640 : {}
119 :
120 35280 : XcsParser::~XcsParser() {}
121 :
122 1982400 : xmlreader::XmlReader::Text XcsParser::getTextMode() {
123 1982400 : return valueParser_.getTextMode();
124 : }
125 :
126 884856 : bool XcsParser::startElement(
127 : xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name,
128 : std::set< OUString > const * existingDependencies)
129 : {
130 884856 : if (valueParser_.startElement(reader, nsId, name, existingDependencies)) {
131 5208 : return true;
132 : }
133 879648 : if (state_ == STATE_START) {
134 35280 : if (nsId == ParseManager::NAMESPACE_OOR &&
135 17640 : name.equals("component-schema"))
136 : {
137 17640 : handleComponentSchema(reader);
138 17640 : state_ = STATE_COMPONENT_SCHEMA;
139 17640 : ignoring_ = 0;
140 17640 : return true;
141 : }
142 : } else {
143 : //TODO: ignoring component-schema import, component-schema uses, and
144 : // prop constraints; accepting all four at illegal places (and with
145 : // illegal content):
146 862008 : if (ignoring_ > 0 ||
147 862008 : (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
148 2586024 : (name.equals("info") || name.equals("import") ||
149 1724016 : name.equals("uses") || name.equals("constraints"))))
150 : {
151 : assert(ignoring_ < LONG_MAX);
152 0 : ++ignoring_;
153 0 : return true;
154 : }
155 862008 : switch (state_) {
156 : case STATE_COMPONENT_SCHEMA:
157 35280 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
158 17640 : name.equals("templates"))
159 : {
160 16128 : state_ = STATE_TEMPLATES;
161 16128 : return true;
162 : }
163 : // fall through
164 : case STATE_TEMPLATES_DONE:
165 35280 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
166 17640 : name.equals("component"))
167 : {
168 17640 : state_ = STATE_COMPONENT;
169 : assert(elements_.empty());
170 : elements_.push(
171 : Element(
172 35280 : new GroupNode(valueParser_.getLayer(), false, ""),
173 52920 : componentName_));
174 17640 : return true;
175 : }
176 0 : break;
177 : case STATE_TEMPLATES:
178 198072 : if (elements_.empty()) {
179 65184 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
180 32592 : name.equals("group"))
181 : {
182 31080 : handleGroup(reader, true);
183 31080 : return true;
184 : }
185 3024 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
186 1512 : name.equals("set"))
187 : {
188 1512 : handleSet(reader, true);
189 1512 : return true;
190 : }
191 0 : break;
192 : }
193 : // fall through
194 : case STATE_COMPONENT:
195 : assert(!elements_.empty());
196 795648 : switch (elements_.top().node->kind()) {
197 : case Node::KIND_PROPERTY:
198 : case Node::KIND_LOCALIZED_PROPERTY:
199 498960 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
200 249480 : name.equals("value"))
201 : {
202 249480 : handlePropValue(reader, elements_.top().node);
203 249480 : return true;
204 : }
205 0 : break;
206 : case Node::KIND_GROUP:
207 1092336 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
208 546168 : name.equals("prop"))
209 : {
210 404544 : handleProp(reader);
211 404544 : return true;
212 : }
213 283248 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
214 141624 : name.equals("node-ref"))
215 : {
216 6720 : handleNodeRef(reader);
217 6720 : return true;
218 : }
219 269808 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
220 134904 : name.equals("group"))
221 : {
222 95928 : handleGroup(reader, false);
223 95928 : return true;
224 : }
225 77952 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
226 38976 : name.equals("set"))
227 : {
228 38976 : handleSet(reader, false);
229 38976 : return true;
230 : }
231 0 : break;
232 : case Node::KIND_SET:
233 0 : if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
234 0 : name.equals("item"))
235 : {
236 : handleSetItem(
237 : reader,
238 0 : static_cast< SetNode * >(elements_.top().node.get()));
239 0 : return true;
240 : }
241 0 : break;
242 : default: // Node::KIND_LOCALIZED_VALUE
243 : assert(false); // this cannot happen
244 0 : break;
245 : }
246 0 : break;
247 : case STATE_COMPONENT_DONE:
248 0 : break;
249 : default: // STATE_START
250 : assert(false); // this cannot happen
251 0 : break;
252 : }
253 : }
254 : throw css::uno::RuntimeException(
255 0 : "bad member <" + name.convertFromUtf8() + "> in " + reader.getUrl(),
256 0 : css::uno::Reference< css::uno::XInterface >());
257 : }
258 :
259 884856 : void XcsParser::endElement(xmlreader::XmlReader const & reader) {
260 884856 : if (valueParser_.endElement()) {
261 1139544 : return;
262 : }
263 630168 : if (ignoring_ > 0) {
264 0 : --ignoring_;
265 630168 : } else if (!elements_.empty()) {
266 596400 : Element top(elements_.top());
267 596400 : elements_.pop();
268 596400 : if (top.node.is()) {
269 596400 : if (elements_.empty()) {
270 50232 : switch (state_) {
271 : case STATE_TEMPLATES:
272 : {
273 32592 : NodeMap::iterator i(data_.templates.find(top.name));
274 32592 : if (i == data_.templates.end()) {
275 : data_.templates.insert(
276 32592 : NodeMap::value_type(top.name, top.node));
277 : } else {
278 0 : merge(i->second, top.node);
279 : }
280 : }
281 32592 : break;
282 : case STATE_COMPONENT:
283 : {
284 17640 : NodeMap & components = data_.getComponents();
285 17640 : NodeMap::iterator i(components.find(top.name));
286 17640 : if (i == components.end()) {
287 : components.insert(
288 17640 : NodeMap::value_type(top.name, top.node));
289 : } else {
290 0 : merge(i->second, top.node);
291 : }
292 17640 : state_ = STATE_COMPONENT_DONE;
293 : }
294 17640 : break;
295 : default:
296 : assert(false);
297 : throw css::uno::RuntimeException(
298 : "this cannot happen",
299 0 : css::uno::Reference< css::uno::XInterface >());
300 : }
301 : } else {
302 1638504 : if (!elements_.top().node->getMembers().insert(
303 1638504 : NodeMap::value_type(top.name, top.node)).second)
304 : {
305 : throw css::uno::RuntimeException(
306 0 : "duplicate " + top.name + " in " + reader.getUrl(),
307 0 : css::uno::Reference< css::uno::XInterface >());
308 : }
309 : }
310 596400 : }
311 : } else {
312 33768 : switch (state_) {
313 : case STATE_COMPONENT_SCHEMA:
314 : // To support old, broken extensions with .xcs files that contain
315 : // empty <component-schema> elements:
316 0 : state_ = STATE_COMPONENT_DONE;
317 0 : break;
318 : case STATE_TEMPLATES:
319 16128 : state_ = STATE_TEMPLATES_DONE;
320 16128 : break;
321 : case STATE_TEMPLATES_DONE:
322 : throw css::uno::RuntimeException(
323 0 : "no component element in " + reader.getUrl(),
324 0 : css::uno::Reference< css::uno::XInterface >());
325 : case STATE_COMPONENT_DONE:
326 17640 : break;
327 : default:
328 : assert(false); // this cannot happen
329 : }
330 : }
331 : }
332 :
333 230328 : void XcsParser::characters(xmlreader::Span const & text) {
334 230328 : valueParser_.characters(text);
335 230328 : }
336 :
337 17640 : void XcsParser::handleComponentSchema(xmlreader::XmlReader & reader) {
338 : //TODO: oor:version, xml:lang attributes
339 17640 : OStringBuffer buf;
340 17640 : buf.append('.');
341 17640 : bool hasPackage = false;
342 17640 : bool hasName = false;
343 : for (;;) {
344 : int attrNsId;
345 70560 : xmlreader::Span attrLn;
346 70560 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
347 17640 : break;
348 : }
349 52920 : if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn.equals("package"))
350 : {
351 17640 : if (hasPackage) {
352 : throw css::uno::RuntimeException(
353 0 : ("multiple component-schema package attributes in " +
354 0 : reader.getUrl()),
355 0 : css::uno::Reference< css::uno::XInterface >());
356 : }
357 17640 : hasPackage = true;
358 17640 : xmlreader::Span s(reader.getAttributeValue(false));
359 17640 : buf.insert(0, s.begin, s.length);
360 52920 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
361 17640 : attrLn.equals("name"))
362 : {
363 17640 : if (hasName) {
364 : throw css::uno::RuntimeException(
365 0 : ("multiple component-schema name attributes in " +
366 0 : reader.getUrl()),
367 0 : css::uno::Reference< css::uno::XInterface >());
368 : }
369 17640 : hasName = true;
370 17640 : xmlreader::Span s(reader.getAttributeValue(false));
371 17640 : buf.append(s.begin, s.length);
372 : }
373 52920 : }
374 17640 : if (!hasPackage) {
375 : throw css::uno::RuntimeException(
376 0 : "no component-schema package attribute in " + reader.getUrl(),
377 0 : css::uno::Reference< css::uno::XInterface >());
378 : }
379 17640 : if (!hasName) {
380 : throw css::uno::RuntimeException(
381 0 : "no component-schema name attribute in " + reader.getUrl(),
382 0 : css::uno::Reference< css::uno::XInterface >());
383 : }
384 35280 : componentName_ = xmlreader::Span(buf.getStr(), buf.getLength()).
385 35280 : convertFromUtf8();
386 17640 : }
387 :
388 6720 : void XcsParser::handleNodeRef(xmlreader::XmlReader & reader) {
389 6720 : bool hasName = false;
390 6720 : OUString name;
391 13440 : OUString component(componentName_);
392 6720 : bool hasNodeType = false;
393 13440 : OUString nodeType;
394 : for (;;) {
395 : int attrNsId;
396 20160 : xmlreader::Span attrLn;
397 20160 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
398 6720 : break;
399 : }
400 13440 : if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn.equals("name")) {
401 6720 : hasName = true;
402 6720 : name = reader.getAttributeValue(false).convertFromUtf8();
403 13440 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
404 6720 : attrLn.equals("component"))
405 : {
406 0 : component = reader.getAttributeValue(false).convertFromUtf8();
407 13440 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
408 6720 : attrLn.equals("node-type"))
409 : {
410 6720 : hasNodeType = true;
411 6720 : nodeType = reader.getAttributeValue(false).convertFromUtf8();
412 : }
413 13440 : }
414 6720 : if (!hasName) {
415 : throw css::uno::RuntimeException(
416 0 : "no node-ref name attribute in " + reader.getUrl(),
417 0 : css::uno::Reference< css::uno::XInterface >());
418 : }
419 : rtl::Reference< Node > tmpl(
420 : data_.getTemplate(
421 : valueParser_.getLayer(),
422 : xmldata::parseTemplateReference(
423 13440 : component, hasNodeType, nodeType, 0)));
424 6720 : if (!tmpl.is()) {
425 : //TODO: this can erroneously happen as long as import/uses attributes
426 : // are not correctly processed
427 : throw css::uno::RuntimeException(
428 0 : "unknown node-ref " + name + " in " + reader.getUrl(),
429 0 : css::uno::Reference< css::uno::XInterface >());
430 : }
431 13440 : rtl::Reference< Node > node(tmpl->clone(false));
432 6720 : node->setLayer(valueParser_.getLayer());
433 13440 : elements_.push(Element(node, name));
434 6720 : }
435 :
436 404544 : void XcsParser::handleProp(xmlreader::XmlReader & reader) {
437 404544 : bool hasName = false;
438 404544 : OUString name;
439 404544 : valueParser_.type_ = TYPE_ERROR;
440 404544 : bool localized = false;
441 404544 : bool nillable = true;
442 : for (;;) {
443 : int attrNsId;
444 1476384 : xmlreader::Span attrLn;
445 1476384 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
446 404544 : break;
447 : }
448 1071840 : if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn.equals("name")) {
449 404544 : hasName = true;
450 404544 : name = reader.getAttributeValue(false).convertFromUtf8();
451 1334592 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
452 667296 : attrLn.equals("type"))
453 : {
454 : valueParser_.type_ = xmldata::parseType(
455 404544 : reader, reader.getAttributeValue(true));
456 525504 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
457 262752 : attrLn.equals("localized"))
458 : {
459 34944 : localized = xmldata::parseBoolean(reader.getAttributeValue(true));
460 455616 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
461 227808 : attrLn.equals("nillable"))
462 : {
463 227808 : nillable = xmldata::parseBoolean(reader.getAttributeValue(true));
464 : }
465 1071840 : }
466 404544 : if (!hasName) {
467 : throw css::uno::RuntimeException(
468 0 : "no prop name attribute in " + reader.getUrl(),
469 0 : css::uno::Reference< css::uno::XInterface >());
470 : }
471 404544 : if (valueParser_.type_ == TYPE_ERROR) {
472 : throw css::uno::RuntimeException(
473 0 : "no prop type attribute in " + reader.getUrl(),
474 0 : css::uno::Reference< css::uno::XInterface >());
475 : }
476 : elements_.push(
477 : Element(
478 : (localized
479 : ? rtl::Reference< Node >(
480 : new LocalizedPropertyNode(
481 66864 : valueParser_.getLayer(), valueParser_.type_, nillable))
482 : : rtl::Reference< Node >(
483 : new PropertyNode(
484 371112 : valueParser_.getLayer(), valueParser_.type_, nillable,
485 371112 : css::uno::Any(), false))),
486 1213632 : name));
487 404544 : }
488 :
489 249480 : void XcsParser::handlePropValue(
490 : xmlreader::XmlReader & reader, rtl::Reference< Node > const & property)
491 : {
492 249480 : xmlreader::Span attrSeparator;
493 : for (;;) {
494 : int attrNsId;
495 250824 : xmlreader::Span attrLn;
496 250824 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
497 249480 : break;
498 : }
499 2688 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
500 1344 : attrLn.equals("separator"))
501 : {
502 1344 : attrSeparator = reader.getAttributeValue(false);
503 1344 : if (attrSeparator.length == 0) {
504 : throw css::uno::RuntimeException(
505 0 : "bad oor:separator attribute in " + reader.getUrl(),
506 0 : css::uno::Reference< css::uno::XInterface >());
507 : }
508 : }
509 1344 : }
510 498960 : valueParser_.separator_ = OString(
511 249480 : attrSeparator.begin, attrSeparator.length);
512 498960 : valueParser_.start(property);
513 249480 : }
514 :
515 127008 : void XcsParser::handleGroup(xmlreader::XmlReader & reader, bool isTemplate) {
516 127008 : bool hasName = false;
517 127008 : OUString name;
518 127008 : bool extensible = false;
519 : for (;;) {
520 : int attrNsId;
521 258048 : xmlreader::Span attrLn;
522 258048 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
523 127008 : break;
524 : }
525 131040 : if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn.equals("name")) {
526 127008 : hasName = true;
527 127008 : name = reader.getAttributeValue(false).convertFromUtf8();
528 8064 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
529 4032 : attrLn.equals("extensible"))
530 : {
531 3864 : extensible = xmldata::parseBoolean(reader.getAttributeValue(true));
532 : }
533 131040 : }
534 127008 : if (!hasName) {
535 : throw css::uno::RuntimeException(
536 0 : "no group name attribute in " + reader.getUrl(),
537 0 : css::uno::Reference< css::uno::XInterface >());
538 : }
539 127008 : if (isTemplate) {
540 31080 : name = Data::fullTemplateName(componentName_, name);
541 : }
542 : elements_.push(
543 : Element(
544 : new GroupNode(
545 127008 : valueParser_.getLayer(), extensible,
546 127008 : isTemplate ? name : OUString()),
547 254016 : name));
548 127008 : }
549 :
550 40488 : void XcsParser::handleSet(xmlreader::XmlReader & reader, bool isTemplate) {
551 40488 : bool hasName = false;
552 40488 : OUString name;
553 80976 : OUString component(componentName_);
554 40488 : bool hasNodeType = false;
555 80976 : OUString nodeType;
556 : for (;;) {
557 : int attrNsId;
558 128856 : xmlreader::Span attrLn;
559 128856 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
560 40488 : break;
561 : }
562 88368 : if (attrNsId == ParseManager::NAMESPACE_OOR && attrLn.equals("name")) {
563 40488 : hasName = true;
564 40488 : name = reader.getAttributeValue(false).convertFromUtf8();
565 95760 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
566 47880 : attrLn.equals("component"))
567 : {
568 7392 : component = reader.getAttributeValue(false).convertFromUtf8();
569 80976 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
570 40488 : attrLn.equals("node-type"))
571 : {
572 40488 : hasNodeType = true;
573 40488 : nodeType = reader.getAttributeValue(false).convertFromUtf8();
574 : }
575 88368 : }
576 40488 : if (!hasName) {
577 : throw css::uno::RuntimeException(
578 0 : "no set name attribute in " + reader.getUrl(),
579 0 : css::uno::Reference< css::uno::XInterface >());
580 : }
581 40488 : if (isTemplate) {
582 1512 : name = Data::fullTemplateName(componentName_, name);
583 : }
584 : elements_.push(
585 : Element(
586 : new SetNode(
587 40488 : valueParser_.getLayer(),
588 : xmldata::parseTemplateReference(
589 : component, hasNodeType, nodeType, 0),
590 40488 : isTemplate ? name : OUString()),
591 121464 : name));
592 40488 : }
593 :
594 0 : void XcsParser::handleSetItem(xmlreader::XmlReader & reader, SetNode * set) {
595 0 : OUString component(componentName_);
596 0 : bool hasNodeType = false;
597 0 : OUString nodeType;
598 : for (;;) {
599 : int attrNsId;
600 0 : xmlreader::Span attrLn;
601 0 : if (!reader.nextAttribute(&attrNsId, &attrLn)) {
602 0 : break;
603 : }
604 0 : if (attrNsId == ParseManager::NAMESPACE_OOR &&
605 0 : attrLn.equals("component"))
606 : {
607 0 : component = reader.getAttributeValue(false).convertFromUtf8();
608 0 : } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
609 0 : attrLn.equals("node-type"))
610 : {
611 0 : hasNodeType = true;
612 0 : nodeType = reader.getAttributeValue(false).convertFromUtf8();
613 : }
614 0 : }
615 0 : set->getAdditionalTemplateNames().push_back(
616 0 : xmldata::parseTemplateReference(component, hasNodeType, nodeType, 0));
617 0 : elements_.push(Element(rtl::Reference< Node >(), ""));
618 0 : }
619 :
620 : }
621 :
622 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|