1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #include "ElemAttribute.hpp"
19 
20 
21 
22 #include <xercesc/sax/AttributeList.hpp>
23 
24 
25 
26 #include <xalanc/PlatformSupport/DOMStringHelper.hpp>
27 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
28 #include <xalanc/PlatformSupport/XalanUnicode.hpp>
29 
30 
31 
32 #include <xalanc/DOMSupport/DOMServices.hpp>
33 
34 
35 
36 #include "AVT.hpp"
37 #include "Constants.hpp"
38 #include "StylesheetConstructionContext.hpp"
39 #include "StylesheetExecutionContext.hpp"
40 
41 
42 
43 namespace XALAN_CPP_NAMESPACE {
44 
45 
46 
47 typedef StylesheetExecutionContext::GetCachedString     GetCachedString;
48 
49 
50 
ElemAttribute(StylesheetConstructionContext & constructionContext,Stylesheet & stylesheetTree,const AttributeListType & atts,XalanFileLoc lineNumber,XalanFileLoc columnNumber)51 ElemAttribute::ElemAttribute(
52             StylesheetConstructionContext&  constructionContext,
53             Stylesheet&                     stylesheetTree,
54             const AttributeListType&        atts,
55             XalanFileLoc                    lineNumber,
56             XalanFileLoc                    columnNumber) :
57     ElemTemplateElement(constructionContext,
58                         stylesheetTree,
59                         lineNumber,
60                         columnNumber,
61                         StylesheetConstructionContext::ELEMNAME_ATTRIBUTE),
62     m_nameAVT(0),
63     m_namespaceAVT(0)
64 {
65     const XalanSize_t   nAttrs = atts.getLength();
66 
67     for (XalanSize_t i = 0; i < nAttrs; i++)
68     {
69         const XalanDOMChar* const   aname = atts.getName(i);
70 
71         if(equals(aname, Constants::ATTRNAME_NAME))
72         {
73             m_nameAVT =
74                 constructionContext.createAVT(getLocator(), aname, atts.getValue(i), *this);
75         }
76         else if(equals(aname, Constants::ATTRNAME_NAMESPACE))
77         {
78             m_namespaceAVT =
79                 constructionContext.createAVT(getLocator(), aname, atts.getValue(i), *this);
80         }
81         else if(isAttrOK(
82                     aname,
83                     atts,
84                     i,
85                     constructionContext) == false &&
86                 processSpaceAttr(
87                     Constants::ELEMNAME_ATTRIBUTE_WITH_PREFIX_STRING.c_str(),
88                     aname,
89                     atts,
90                     i,
91                     constructionContext) == false)
92         {
93             error(
94                 constructionContext,
95                 XalanMessages::ElementHasIllegalAttribute_2Param,
96                 Constants::ELEMNAME_ATTRIBUTE_WITH_PREFIX_STRING.c_str(),
97                 aname);
98         }
99     }
100 
101     if(0 == m_nameAVT)
102     {
103         XalanDOMString  theResult(constructionContext.getMemoryManager());
104 
105         error(
106             constructionContext,
107             XalanMessages::ElementMustHaveAttribute_2Param,
108             Constants::ELEMNAME_ATTRIBUTE_WITH_PREFIX_STRING,
109             Constants::ATTRNAME_NAME);
110     }
111 }
112 
113 
114 
~ElemAttribute()115 ElemAttribute::~ElemAttribute()
116 {
117 }
118 
119 
120 
121 const XalanDOMString&
getElementName() const122 ElemAttribute::getElementName() const
123 {
124     return Constants::ELEMNAME_ATTRIBUTE_WITH_PREFIX_STRING;
125 }
126 
127 
128 
129 #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
130 const ElemTemplateElement*
startElement(StylesheetExecutionContext & executionContext) const131 ElemAttribute::startElement(StylesheetExecutionContext& executionContext) const
132 {
133     assert(m_nameAVT != 0);
134 
135     ElemTemplateElement::startElement(executionContext);
136 
137     XalanDOMString&     attrName = executionContext.getAndPushCachedString();
138 
139     m_nameAVT->evaluate(attrName, *this, executionContext);
140 
141     if(XalanQName::isValidQName(attrName) == false)
142     {
143         warn(
144             executionContext,
145             XalanMessages::AttributeNameNotValidQName_1Param,
146             attrName);
147 
148         executionContext.pushProcessCurrentAttribute(false);
149     }
150     else
151     {
152         // save original attribute name
153         const GetCachedString   origAttrNameGuard(executionContext);
154 
155         XalanDOMString&     origAttrName = origAttrNameGuard.get();
156 
157         origAttrName.assign(attrName);
158 
159         const XalanDOMString::size_type     origAttrNameLength = origAttrName.length();
160 
161         XalanDOMString::size_type           indexOfNSSep = 0;
162 
163         const GetCachedString   attrNameSpaceGuard(executionContext);
164 
165         XalanDOMString&     attrNameSpace = attrNameSpaceGuard.get();
166 
167         if(0 != m_namespaceAVT)
168         {
169             m_namespaceAVT->evaluate(attrNameSpace, *this, executionContext);
170 
171             indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);
172 
173             if (attrNameSpace.empty())
174             {
175                 // If there's no namespace, but the attribute has a
176                 // prefix, then we must strip the prefix off.
177                 if (indexOfNSSep < origAttrNameLength)
178                 {
179                     substring(origAttrName, attrName, indexOfNSSep + 1);
180                 }
181 
182                 // We set this to indicate that there is no prefix any
183                 // longer.
184                 indexOfNSSep = origAttrNameLength;
185             }
186             else
187             {
188                 // See if the namespace already exists.  If it does, we'll get the
189                 // prefix that was used when it was declared.
190                 const XalanDOMString*  const    prefix =
191                     executionContext.getResultPrefixForNamespace(attrNameSpace);
192 
193                 // If there is already a prefix for the namespace, and it's length
194                 // is not 0, and there is no prefix on the attribute name, or
195                 // it's equal to the prefix on the attribute, then go ahead
196                 // and use that prefix.
197                 if(prefix != 0 &&
198                    prefix->empty() == false &&
199                    (indexOfNSSep == origAttrNameLength ||
200                     equals(prefix->c_str(), attrName.c_str(), indexOfNSSep) == true))
201                 {
202                     if(indexOfNSSep < origAttrNameLength)
203                     {
204                         attrName.reserve(attrName.length() - (indexOfNSSep + 1) + DOMServices::s_XMLNamespaceSeparatorStringLength + prefix->length() + 1);
205 
206                         attrName.erase(0, indexOfNSSep + 1);
207                     }
208                     else
209                     {
210                         attrName.reserve(
211                             attrName.length() + DOMServices::s_XMLNamespaceSeparatorStringLength + prefix->length() + 1);
212                     }
213 
214                     attrName.insert(0, DOMServices::s_XMLNamespaceSeparatorString);
215                     attrName.insert(0, *prefix);
216                 }
217                 else
218                 {
219                     const GetCachedString   newPrefixGuard(executionContext);
220 
221                     XalanDOMString&     newPrefix = newPrefixGuard.get();
222 
223                     // If the prefix on the QName is xmlns, we cannot use it.
224                     const bool          fPrefixIsXMLNS =
225                         startsWith(origAttrName, DOMServices::s_XMLNamespaceWithSeparator);
226 
227                     // If there's a prefix, and it's not xmlns, then use
228                     // the prefix that's provided.
229                     if(indexOfNSSep < origAttrNameLength &&
230                         fPrefixIsXMLNS == false)
231                     {
232                         substring(origAttrName, newPrefix, 0, indexOfNSSep);
233 
234                         // OK, make sure that the prefix provided maps to
235                         // the same namespace as the one the user requested,
236                         // and see if it's in use...
237                         const XalanDOMString* const theNamespace =
238                             executionContext.getResultNamespaceForPrefix(newPrefix);
239 
240                         if (theNamespace != 0 &&
241                             equals(*theNamespace, attrNameSpace) == false &&
242                             executionContext.isPendingResultPrefix(newPrefix) == true)
243                         {
244                             // It doesn't, so we'll need to manufacture a
245                             // prefix.
246                             newPrefix.clear();
247 
248                             // Strip the user-supplied prefix from the name...
249                             substring(origAttrName, attrName, indexOfNSSep + 1);
250                         }
251                     }
252 
253                     if (newPrefix.empty() == true)
254                     {
255                         // If there's a prefix, and it's xmlns, then strip it
256                         // off...
257                         if (fPrefixIsXMLNS == true)
258                         {
259                             attrName.erase(0, indexOfNSSep + 1);
260                         }
261 
262                         // Get a new, unique namespace prefix...
263                         executionContext.getUniqueNamespaceValue(newPrefix);
264 
265                         // Reserve some space in the string.
266                         attrName.reserve(
267                             attrName.length() + DOMServices::s_XMLNamespaceSeparatorStringLength + newPrefix.length() + 1);
268 
269                         attrName.insert(0, DOMServices::s_XMLNamespaceSeparatorString);
270                         attrName.insert(0, newPrefix);
271                     }
272 
273                     // OK, now we have to generate a namespace declaration...
274                     const GetCachedString   nsDeclGuard(executionContext);
275 
276                     XalanDOMString&     nsDecl = nsDeclGuard.get();
277 
278                     nsDecl.reserve(DOMServices::s_XMLNamespaceWithSeparatorLength + newPrefix.length() + 1);
279 
280                     nsDecl.assign(DOMServices::s_XMLNamespaceWithSeparator);
281 
282                     nsDecl.append(newPrefix);
283 
284                     // Add the namespace declaration...
285                     executionContext.addResultAttribute(nsDecl, attrNameSpace);
286                 }
287             }
288         }
289       // Note we are using original attribute name for these tests.
290         else if(executionContext.isElementPending() == true &&
291                 !equals(origAttrName, DOMServices::s_XMLNamespace))
292         {
293             // Don't try to create a namespace declaration for anything that
294             // starts with xml:
295             if (startsWith(origAttrName, DOMServices::s_XMLString) == true)
296             {
297                 // This just fakes out the test below.  It would be better if
298                 // we had a better way of testing this...
299                 indexOfNSSep = origAttrNameLength;
300             }
301             else
302             {
303                 // make sure that if a prefix is specified on the attribute name, it is valid
304                 indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);
305 
306                 if(indexOfNSSep < origAttrNameLength)
307                 {
308                     const GetCachedString   nsprefixGuard(executionContext);
309 
310                     XalanDOMString&     nsprefix = nsprefixGuard.get();
311 
312                     substring(origAttrName, nsprefix, 0, indexOfNSSep);
313 
314                     const XalanDOMString* const     theNamespace =
315                         getNamespaceForPrefix(nsprefix);
316 
317                     if (theNamespace != 0)
318                     {
319                         attrNameSpace.assign(*theNamespace);
320 
321                         const XalanDOMString* const     theResultNamespace =
322                             executionContext.getResultNamespaceForPrefix(nsprefix);
323 
324                         if (theResultNamespace != 0 &&
325                             *theNamespace != *theResultNamespace)
326                         {
327                             // Oops! There's a conflict between an existing
328                             // result namespace and the attribute's namespace.
329                             // To be safe, because we are generating namespace
330                             // declaration here, rather than somewhere that
331                             // knows more about how that result namespace is
332                             // used, let's change the prefix of the attribute.
333                             nsprefix.clear();
334 
335                             executionContext.getUniqueNamespaceValue(nsprefix);
336 
337                             // Fix the name by removing the original prefix and
338                             // inserting the new one.
339                             attrName.erase(0, indexOfNSSep);
340                             attrName.insert(attrName.begin(), nsprefix.begin(), nsprefix.end());
341                         }
342                     }
343 
344                     if (attrNameSpace.empty())
345                     {
346                         warn(
347                             executionContext,
348                             XalanMessages::PrefixIsNotDeclared_1Param,
349                             nsprefix);
350                     }
351                     else
352                     {
353                         // Check to see if there's already a namespace declaration in scope...
354                         const XalanDOMString* const     prefix =
355                             executionContext.getResultPrefixForNamespace(attrNameSpace);
356 
357                         if (prefix == 0)
358                         {
359                             // We need to generate a namespace declaration...
360                             const GetCachedString   nsDeclGuard(executionContext);
361 
362                             XalanDOMString&     nsDecl = nsDeclGuard.get();
363 
364                             nsDecl.reserve(DOMServices::s_XMLNamespaceWithSeparatorLength + nsprefix.length() + 1);
365 
366                             nsDecl.assign(DOMServices::s_XMLNamespaceWithSeparator);
367 
368                             nsDecl.append(nsprefix);
369 
370                             // Add the namespace declaration...
371                             executionContext.addResultAttribute(nsDecl, attrNameSpace);
372                         }
373                     }
374                 }
375             }
376         }
377         else
378         {
379             warn(
380                 executionContext,
381                 XalanMessages::AttributesCannotBeAdded);
382         }
383 
384         // If there was no namespace, or the namespace was resolved, process
385         // the result attribute.
386 
387         if (indexOfNSSep == origAttrNameLength || !attrNameSpace.empty())
388         {
389             executionContext.pushProcessCurrentAttribute(true);
390             executionContext.pushCopyTextNodesOnly(true);
391 
392             XalanDOMString& theResult = executionContext.getAndPushCachedString();
393 
394             return beginChildrenToString(executionContext,theResult);
395 
396         }
397         else
398         {
399             executionContext.pushProcessCurrentAttribute(false);
400         }
401     }
402 
403     executionContext.getAndPopCachedString();
404 
405     return 0;
406 }
407 
408 
409 
410 void
endElement(StylesheetExecutionContext & executionContext) const411 ElemAttribute::endElement(StylesheetExecutionContext&       executionContext) const
412 {
413     if (executionContext.popProcessCurrentAttribute() == true)
414     {
415         endChildrenToString(executionContext);
416 
417         XalanDOMString& theResult = executionContext.getAndPopCachedString();
418         XalanDOMString& attrName = executionContext.getAndPopCachedString();
419 
420         executionContext.addResultAttribute(attrName,theResult);
421 
422         executionContext.popCopyTextNodesOnly();
423     }
424 }
425 #endif
426 
427 
428 
429 #if defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
430 void
execute(StylesheetExecutionContext & executionContext) const431 ElemAttribute::execute(StylesheetExecutionContext&  executionContext) const
432 {
433     assert(m_nameAVT != 0);
434 
435     ElemTemplateElement::execute(executionContext);
436 
437     const GetCachedString   attrNameGuard(executionContext);
438 
439     XalanDOMString&     attrName = attrNameGuard.get();
440 
441     m_nameAVT->evaluate(attrName, *this, executionContext);
442 
443     if(XalanQName::isValidQName(attrName) == false)
444     {
445         warn(
446             executionContext,
447             XalanMessages::AttributeNameNotValidQName_1Param,
448             attrName);
449     }
450     else
451     {
452         // save original attribute name
453         const GetCachedString   origAttrNameGuard(executionContext);
454 
455         XalanDOMString&     origAttrName = origAttrNameGuard.get();
456 
457         assign(origAttrName, attrName);
458 
459         const XalanDOMString::size_type     origAttrNameLength = length(origAttrName);
460 
461         XalanDOMString::size_type           indexOfNSSep = 0;
462 
463         const GetCachedString   attrNameSpaceGuard(executionContext);
464 
465         XalanDOMString&     attrNameSpace = attrNameSpaceGuard.get();
466 
467         if(0 != m_namespaceAVT)
468         {
469             m_namespaceAVT->evaluate(attrNameSpace, *this, executionContext);
470 
471             indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);
472 
473             if(attrNameSpace.empty())
474             {
475                 // If there's no namespace, but the attribute has a
476                 // prefix, then we must strip the prefix off.
477                 if (indexOfNSSep < origAttrNameLength)
478                 {
479                     substring(origAttrName, attrName, indexOfNSSep + 1);
480                 }
481 
482                 // We set this to indicate that there is no prefix any
483                 // longer.
484                 indexOfNSSep = origAttrNameLength;
485             }
486             else
487             {
488                 // See if the namespace already exists.  If it does, we'll get the
489                 // prefix that was used when it was declared.
490                 const XalanDOMString*  const    prefix =
491                     executionContext.getResultPrefixForNamespace(attrNameSpace);
492 
493                 // If there is already a prefix for the namespace, and it's length
494                 // is not 0, and there is no prefix on the attribute name, or
495                 // it's equal to the prefix on the attribute, then go ahead
496                 // and use that prefix.
497                 if(prefix != 0 &&
498                    length(*prefix) != 0 &&
499                    (indexOfNSSep == origAttrNameLength ||
500                     equals(prefix->c_str(), attrName.c_str(), indexOfNSSep) == true))
501                 {
502                     if(indexOfNSSep < origAttrNameLength)
503                     {
504                         reserve(
505                             attrName,
506                             length(attrName) - (indexOfNSSep + 1) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(*prefix) + 1);
507 
508                         attrName.erase(0, indexOfNSSep + 1);
509                     }
510                     else
511                     {
512                         reserve(
513                             attrName,
514                             length(attrName) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(*prefix) + 1);
515                     }
516 
517                     insert(attrName, 0, DOMServices::s_XMLNamespaceSeparatorString);
518                     insert(attrName, 0, *prefix);
519                 }
520                 else
521                 {
522                     const GetCachedString   newPrefixGuard(executionContext);
523 
524                     XalanDOMString&     newPrefix = newPrefixGuard.get();
525 
526                     // If the prefix on the QName is xmlns, we cannot use it.
527                     const bool          fPrefixIsXMLNS =
528                         startsWith(origAttrName, DOMServices::s_XMLNamespaceWithSeparator);
529 
530                     // If there's a prefix, and it's not xmlns, then use
531                     // the prefix that's provided.
532                     if(indexOfNSSep < origAttrNameLength &&
533                         fPrefixIsXMLNS == false)
534                     {
535                         substring(origAttrName, newPrefix, 0, indexOfNSSep);
536 
537                         // OK, make sure that the prefix provided maps to
538                         // the same namespace as the one the user requested,
539                         // and see if it's in use...
540                         const XalanDOMString* const theNamespace =
541                             executionContext.getResultNamespaceForPrefix(newPrefix);
542 
543                         if (theNamespace != 0 &&
544                             equals(*theNamespace, attrNameSpace) == false &&
545                             executionContext.isPendingResultPrefix(newPrefix) == true)
546                         {
547                             // It doesn't, so we'll need to manufacture a
548                             // prefix.
549                             clear(newPrefix);
550 
551                             // Strip the user-supplied prefix from the name...
552                             substring(origAttrName, attrName, indexOfNSSep + 1);
553                         }
554                     }
555 
556                     if (length(newPrefix) == 0)
557                     {
558                         // If there's a prefix, and it's xmlns, then strip it
559                         // off...
560                         if (fPrefixIsXMLNS == true)
561                         {
562                             attrName.erase(0, indexOfNSSep + 1);
563                         }
564 
565                         // Get a new, unique namespace prefix...
566                         executionContext.getUniqueNamespaceValue(newPrefix);
567 
568                         // Reserve some space in the string.
569                         reserve(
570                             attrName,
571                             length(attrName) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(newPrefix) + 1);
572 
573                         insert(attrName, 0, DOMServices::s_XMLNamespaceSeparatorString);
574                         insert(attrName, 0, newPrefix);
575                     }
576 
577                     // OK, now we have to generate a namespace declaration...
578                     const GetCachedString   nsDeclGuard(executionContext);
579 
580                     XalanDOMString&     nsDecl = nsDeclGuard.get();
581 
582                     reserve(nsDecl, DOMServices::s_XMLNamespaceWithSeparatorLength + length(newPrefix) + 1);
583 
584                     assign(nsDecl, DOMServices::s_XMLNamespaceWithSeparator);
585 
586                     append(nsDecl, newPrefix);
587 
588                     // Add the namespace declaration...
589                     executionContext.addResultAttribute(nsDecl, attrNameSpace);
590                 }
591             }
592         }
593       // Note we are using original attribute name for these tests.
594         else if(executionContext.isElementPending() == true &&
595                 !equals(origAttrName, DOMServices::s_XMLNamespace))
596         {
597             // Don't try to create a namespace declaration for anything that
598             // starts with xml:
599             if (startsWith(origAttrName, DOMServices::s_XMLString) == true)
600             {
601                 // This just fakes out the test below.  It would be better if
602                 // we had a better way of testing this...
603                 indexOfNSSep = origAttrNameLength;
604             }
605             else
606             {
607                 // make sure that if a prefix is specified on the attribute name, it is valid
608                 indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);
609 
610                 if(indexOfNSSep < origAttrNameLength)
611                 {
612                     const GetCachedString   nsprefixGuard(executionContext);
613 
614                     XalanDOMString&     nsprefix = nsprefixGuard.get();
615 
616                     substring(origAttrName, nsprefix, 0, indexOfNSSep);
617 
618                     const XalanDOMString* const     theNamespace =
619                         getNamespaceForPrefix(nsprefix);
620 
621                     if (theNamespace != 0)
622                     {
623                         assign(attrNameSpace, *theNamespace);
624 
625                         const XalanDOMString* const     theResultNamespace =
626                             executionContext.getResultNamespaceForPrefix(nsprefix);
627 
628                         if (theResultNamespace != 0 &&
629                             *theNamespace != *theResultNamespace)
630                         {
631                             // Oops! There's a conflict between an existing
632                             // result namespace and the attribute's namespace.
633                             // To be safe, because we are generating namespace
634                             // declaration here, rather than somewhere that
635                             // knows more about how that result namespace is
636                             // used, let's change the prefix of the attribute.
637                             nsprefix.clear();
638 
639                             executionContext.getUniqueNamespaceValue(nsprefix);
640 
641                             // Fix the name by removing the original prefix and
642                             // inserting the new one.
643                             attrName.erase(0, indexOfNSSep);
644                             attrName.insert(attrName.begin(), nsprefix.begin(), nsprefix.end());
645                         }
646                     }
647 
648                     if (attrNameSpace.empty())
649                     {
650                         // Could not resolve prefix
651                         warn(
652                             executionContext,
653                             XalanMessages::PrefixIsNotDeclared_1Param,
654                             nsprefix);
655                     }
656                     else
657                     {
658                         // Check to see if there's already a namespace declaration in scope...
659                         const XalanDOMString* const     prefix =
660                             executionContext.getResultPrefixForNamespace(attrNameSpace);
661 
662                         if (prefix == 0)
663                         {
664                             // We need to generate a namespace declaration...
665                             const GetCachedString   nsDeclGuard(executionContext);
666 
667                             XalanDOMString&     nsDecl = nsDeclGuard.get();
668 
669                             reserve(nsDecl, DOMServices::s_XMLNamespaceWithSeparatorLength + length(nsprefix) + 1);
670 
671                             assign(nsDecl, DOMServices::s_XMLNamespaceWithSeparator);
672 
673                             append(nsDecl, nsprefix);
674 
675                             // Add the namespace declaration...
676                             executionContext.addResultAttribute(nsDecl, attrNameSpace);
677                         }
678                     }
679                 }
680             }
681         }
682         else
683         {
684             warn(
685                 executionContext,
686                 XalanMessages::AttributesCannotBeAdded);
687         }
688 
689         // If there was no namespace, or the namespace was resolved, process
690         // the result attribute.
691         if (indexOfNSSep == origAttrNameLength || !attrNameSpace.empty())
692         {
693             StylesheetExecutionContext::SetAndRestoreCopyTextNodesOnly  theSetAndRestore(executionContext, true);
694 
695             childrenToResultAttribute(
696                 executionContext,
697                 attrName);
698         }
699     }
700 }
701 #endif
702 
703 
704 
705 bool
childTypeAllowed(int xslToken) const706 ElemAttribute::childTypeAllowed(int     xslToken) const
707 {
708     bool    fResult = false;
709 
710     switch(xslToken)
711     {
712         // char-instructions
713     case StylesheetConstructionContext::ELEMNAME_TEXT_LITERAL_RESULT:
714     case StylesheetConstructionContext::ELEMNAME_APPLY_TEMPLATES:
715     case StylesheetConstructionContext::ELEMNAME_APPLY_IMPORTS:
716     case StylesheetConstructionContext::ELEMNAME_CALL_TEMPLATE:
717     case StylesheetConstructionContext::ELEMNAME_FOR_EACH:
718     case StylesheetConstructionContext::ELEMNAME_VALUE_OF:
719     case StylesheetConstructionContext::ELEMNAME_COPY_OF:
720     case StylesheetConstructionContext::ELEMNAME_NUMBER:
721     case StylesheetConstructionContext::ELEMNAME_CHOOSE:
722     case StylesheetConstructionContext::ELEMNAME_IF:
723     case StylesheetConstructionContext::ELEMNAME_TEXT:
724     case StylesheetConstructionContext::ELEMNAME_COPY:
725     case StylesheetConstructionContext::ELEMNAME_VARIABLE:
726     case StylesheetConstructionContext::ELEMNAME_MESSAGE:
727         fResult = true;
728         break;
729 
730     default:
731         break;
732     }
733 
734     return fResult;
735 }
736 
737 
738 
739 }
740