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