xref: /trunk/main/configmgr/source/xcsparser.cxx (revision 3a7cf181)
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