001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: XSLTElementDef.java 468640 2006-10-28 06:53:53Z minchau $
020 */
021 package org.apache.xalan.processor;
022
023 import java.util.Enumeration;
024 import java.util.Hashtable;
025
026 import org.apache.xalan.templates.Constants;
027 import org.apache.xml.utils.QName;
028
029 /**
030 * This class defines the allowed structure for an element in a XSLT stylesheet,
031 * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the
032 * mapping between Xalan classes and the markup elements in the XSLT instance.
033 * This actually represents both text nodes and elements.
034 */
035 public class XSLTElementDef
036 {
037
038 /**
039 * Construct an instance of XSLTElementDef. This must be followed by a
040 * call to build().
041 */
042 XSLTElementDef(){}
043
044 /**
045 * Construct an instance of XSLTElementDef.
046 *
047 * @param namespace The Namespace URI, "*", or null.
048 * @param name The local name (without prefix), "*", or null.
049 * @param nameAlias A potential alias for the name, or null.
050 * @param elements An array of allowed child element defs, or null.
051 * @param attributes An array of allowed attribute defs, or null.
052 * @param contentHandler The element processor for this element.
053 * @param classObject The class of the object that this element def should produce.
054 */
055 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
056 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
057 XSLTElementProcessor contentHandler, Class classObject)
058 {
059 build(namespace, name, nameAlias, elements, attributes, contentHandler,
060 classObject);
061 if ( (null != namespace)
062 && (namespace.equals(Constants.S_XSLNAMESPACEURL)
063 || namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL)
064 || namespace.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL)))
065 {
066 schema.addAvailableElement(new QName(namespace, name));
067 if(null != nameAlias)
068 schema.addAvailableElement(new QName(namespace, nameAlias));
069 }
070 }
071
072 /**
073 * Construct an instance of XSLTElementDef.
074 *
075 * @param namespace The Namespace URI, "*", or null.
076 * @param name The local name (without prefix), "*", or null.
077 * @param nameAlias A potential alias for the name, or null.
078 * @param elements An array of allowed child element defs, or null.
079 * @param attributes An array of allowed attribute defs, or null.
080 * @param contentHandler The element processor for this element.
081 * @param classObject The class of the object that this element def should produce.
082 * @param has_required true if this element has required elements by the XSLT specification.
083 */
084 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
085 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
086 XSLTElementProcessor contentHandler, Class classObject, boolean has_required)
087 {
088 this.m_has_required = has_required;
089 build(namespace, name, nameAlias, elements, attributes, contentHandler,
090 classObject);
091 if ( (null != namespace)
092 && (namespace.equals(Constants.S_XSLNAMESPACEURL)
093 || namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL)
094 || namespace.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL)))
095 {
096 schema.addAvailableElement(new QName(namespace, name));
097 if(null != nameAlias)
098 schema.addAvailableElement(new QName(namespace, nameAlias));
099 }
100
101 }
102
103 /**
104 * Construct an instance of XSLTElementDef.
105 *
106 * @param namespace The Namespace URI, "*", or null.
107 * @param name The local name (without prefix), "*", or null.
108 * @param nameAlias A potential alias for the name, or null.
109 * @param elements An array of allowed child element defs, or null.
110 * @param attributes An array of allowed attribute defs, or null.
111 * @param contentHandler The element processor for this element.
112 * @param classObject The class of the object that this element def should produce.
113 * @param has_required true if this element has required elements by the XSLT specification.
114 * @param required true if this element is required by the XSLT specification.
115 */
116 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
117 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
118 XSLTElementProcessor contentHandler, Class classObject,
119 boolean has_required, boolean required)
120 {
121 this(schema, namespace, name, nameAlias,
122 elements, attributes,
123 contentHandler, classObject, has_required);
124 this.m_required = required;
125 }
126
127 /**
128 * Construct an instance of XSLTElementDef.
129 *
130 * @param namespace The Namespace URI, "*", or null.
131 * @param name The local name (without prefix), "*", or null.
132 * @param nameAlias A potential alias for the name, or null.
133 * @param elements An array of allowed child element defs, or null.
134 * @param attributes An array of allowed attribute defs, or null.
135 * @param contentHandler The element processor for this element.
136 * @param classObject The class of the object that this element def should produce.
137 * @param has_required true if this element has required elements by the XSLT specification.
138 * @param required true if this element is required by the XSLT specification.
139 * @param order the order this element should appear according to the XSLT specification.
140 * @param multiAllowed whether this element is allowed more than once
141 */
142 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
143 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
144 XSLTElementProcessor contentHandler, Class classObject,
145 boolean has_required, boolean required, int order,
146 boolean multiAllowed)
147 {
148 this(schema, namespace, name, nameAlias,
149 elements, attributes,
150 contentHandler, classObject, has_required, required);
151 this.m_order = order;
152 this.m_multiAllowed = multiAllowed;
153 }
154
155 /**
156 * Construct an instance of XSLTElementDef.
157 *
158 * @param namespace The Namespace URI, "*", or null.
159 * @param name The local name (without prefix), "*", or null.
160 * @param nameAlias A potential alias for the name, or null.
161 * @param elements An array of allowed child element defs, or null.
162 * @param attributes An array of allowed attribute defs, or null.
163 * @param contentHandler The element processor for this element.
164 * @param classObject The class of the object that this element def should produce.
165 * @param has_required true if this element has required elements by the XSLT specification.
166 * @param required true if this element is required by the XSLT specification.
167 * @param has_order whether this element has ordered child elements
168 * @param order the order this element should appear according to the XSLT specification.
169 * @param multiAllowed whether this element is allowed more than once
170 */
171 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
172 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
173 XSLTElementProcessor contentHandler, Class classObject,
174 boolean has_required, boolean required, boolean has_order, int order,
175 boolean multiAllowed)
176 {
177 this(schema, namespace, name, nameAlias,
178 elements, attributes,
179 contentHandler, classObject, has_required, required);
180 this.m_order = order;
181 this.m_multiAllowed = multiAllowed;
182 this.m_isOrdered = has_order;
183 }
184
185 /**
186 * Construct an instance of XSLTElementDef.
187 *
188 * @param namespace The Namespace URI, "*", or null.
189 * @param name The local name (without prefix), "*", or null.
190 * @param nameAlias A potential alias for the name, or null.
191 * @param elements An array of allowed child element defs, or null.
192 * @param attributes An array of allowed attribute defs, or null.
193 * @param contentHandler The element processor for this element.
194 * @param classObject The class of the object that this element def should produce.
195 * @param has_order whether this element has ordered child elements
196 * @param order the order this element should appear according to the XSLT specification.
197 * @param multiAllowed whether this element is allowed more than once
198 */
199 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
200 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
201 XSLTElementProcessor contentHandler, Class classObject,
202 boolean has_order, int order, boolean multiAllowed)
203 {
204 this(schema, namespace, name, nameAlias,
205 elements, attributes,
206 contentHandler, classObject,
207 order, multiAllowed);
208 this.m_isOrdered = has_order;
209 }
210
211 /**
212 * Construct an instance of XSLTElementDef.
213 *
214 * @param namespace The Namespace URI, "*", or null.
215 * @param name The local name (without prefix), "*", or null.
216 * @param nameAlias A potential alias for the name, or null.
217 * @param elements An array of allowed child element defs, or null.
218 * @param attributes An array of allowed attribute defs, or null.
219 * @param contentHandler The element processor for this element.
220 * @param classObject The class of the object that this element def should produce.
221 * @param order the order this element should appear according to the XSLT specification.
222 * @param multiAllowed whether this element is allowed more than once
223 */
224 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
225 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
226 XSLTElementProcessor contentHandler, Class classObject,
227 int order, boolean multiAllowed)
228 {
229 this(schema, namespace, name, nameAlias, elements, attributes, contentHandler,
230 classObject);
231 this.m_order = order;
232 this.m_multiAllowed = multiAllowed;
233 }
234
235 /**
236 * Construct an instance of XSLTElementDef that represents text.
237 *
238 * @param classObject The class of the object that this element def should produce.
239 * @param contentHandler The element processor for this element.
240 * @param type Content type, one of T_ELEMENT, T_PCDATA, or T_ANY.
241 */
242 XSLTElementDef(Class classObject, XSLTElementProcessor contentHandler,
243 int type)
244 {
245
246 this.m_classObject = classObject;
247 this.m_type = type;
248
249 setElementProcessor(contentHandler);
250 }
251
252 /**
253 * Construct an instance of XSLTElementDef.
254 *
255 * @param namespace The Namespace URI, "*", or null.
256 * @param name The local name (without prefix), "*", or null.
257 * @param nameAlias A potential alias for the name, or null.
258 * @param elements An array of allowed child element defs, or null.
259 * @param attributes An array of allowed attribute defs, or null.
260 * @param contentHandler The element processor for this element.
261 * @param classObject The class of the object that this element def should produce.
262 */
263 void build(String namespace, String name, String nameAlias,
264 XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
265 XSLTElementProcessor contentHandler, Class classObject)
266 {
267
268 this.m_namespace = namespace;
269 this.m_name = name;
270 this.m_nameAlias = nameAlias;
271 this.m_elements = elements;
272 this.m_attributes = attributes;
273
274 setElementProcessor(contentHandler);
275
276 this.m_classObject = classObject;
277
278 if (hasRequired() && m_elements != null)
279 {
280 int n = m_elements.length;
281 for (int i = 0; i < n; i++)
282 {
283 XSLTElementDef def = m_elements[i];
284
285 if (def != null && def.getRequired())
286 {
287 if (m_requiredFound == null)
288 m_requiredFound = new Hashtable();
289 m_requiredFound.put(def.getName(), "xsl:" +def.getName());
290 }
291 }
292 }
293 }
294
295 /**
296 * Tell if two objects are equal, when either one may be null.
297 * If both are null, they are considered equal.
298 *
299 * @param obj1 A reference to the first object, or null.
300 * @param obj2 A reference to the second object, or null.
301 *
302 * @return true if the to objects are equal by both being null or
303 * because obj2.equals(obj1) returns true.
304 */
305 private static boolean equalsMayBeNull(Object obj1, Object obj2)
306 {
307 return (obj2 == obj1)
308 || ((null != obj1) && (null != obj2) && obj2.equals(obj1));
309 }
310
311 /**
312 * Tell if the two string refs are equal,
313 * equality being defined as:
314 * 1) Both strings are null.
315 * 2) One string is null and the other is empty.
316 * 3) Both strings are non-null, and equal.
317 *
318 * @param s1 A reference to the first string, or null.
319 * @param s2 A reference to the second string, or null.
320 *
321 * @return true if Both strings are null, or if
322 * one string is null and the other is empty, or if
323 * both strings are non-null, and equal because
324 * s1.equals(s2) returns true.
325 */
326 private static boolean equalsMayBeNullOrZeroLen(String s1, String s2)
327 {
328
329 int len1 = (s1 == null) ? 0 : s1.length();
330 int len2 = (s2 == null) ? 0 : s2.length();
331
332 return (len1 != len2) ? false
333 : (len1 == 0) ? true
334 : s1.equals(s2);
335 }
336
337 /** Content type enumerations */
338 static final int T_ELEMENT = 1, T_PCDATA = 2, T_ANY = 3;
339
340 /**
341 * The type of this element.
342 */
343 private int m_type = T_ELEMENT;
344
345 /**
346 * Get the type of this element.
347 *
348 * @return Content type, one of T_ELEMENT, T_PCDATA, or T_ANY.
349 */
350 int getType()
351 {
352 return m_type;
353 }
354
355 /**
356 * Set the type of this element.
357 *
358 * @param t Content type, one of T_ELEMENT, T_PCDATA, or T_ANY.
359 */
360 void setType(int t)
361 {
362 m_type = t;
363 }
364
365 /**
366 * The allowed namespace for this element.
367 */
368 private String m_namespace;
369
370 /**
371 * Get the allowed namespace for this element.
372 *
373 * @return The Namespace URI, "*", or null.
374 */
375 String getNamespace()
376 {
377 return m_namespace;
378 }
379
380 /**
381 * The name of this element.
382 */
383 private String m_name;
384
385 /**
386 * Get the local name of this element.
387 *
388 * @return The local name of this element, "*", or null.
389 */
390 String getName()
391 {
392 return m_name;
393 }
394
395 /**
396 * The name of this element.
397 */
398 private String m_nameAlias;
399
400 /**
401 * Get the name of this element.
402 *
403 * @return A potential alias for the name, or null.
404 */
405 String getNameAlias()
406 {
407 return m_nameAlias;
408 }
409
410 /**
411 * The allowed elements for this type.
412 */
413 private XSLTElementDef[] m_elements;
414
415 /**
416 * Get the allowed elements for this type.
417 *
418 * @return An array of allowed child element defs, or null.
419 * @xsl.usage internal
420 */
421 public XSLTElementDef[] getElements()
422 {
423 return m_elements;
424 }
425
426 /**
427 * Set the allowed elements for this type.
428 *
429 * @param defs An array of allowed child element defs, or null.
430 */
431 void setElements(XSLTElementDef[] defs)
432 {
433 m_elements = defs;
434 }
435
436 /**
437 * Tell if the namespace URI and local name match this
438 * element.
439 * @param uri The namespace uri, which may be null.
440 * @param localName The local name of an element, which may be null.
441 *
442 * @return true if the uri and local name arguments are considered
443 * to match the uri and local name of this element def.
444 */
445 private boolean QNameEquals(String uri, String localName)
446 {
447
448 return (equalsMayBeNullOrZeroLen(m_namespace, uri)
449 && (equalsMayBeNullOrZeroLen(m_name, localName)
450 || equalsMayBeNullOrZeroLen(m_nameAlias, localName)));
451 }
452
453 /**
454 * Given a namespace URI, and a local name, get the processor
455 * for the element, or return null if not allowed.
456 *
457 * @param uri The Namespace URI, or an empty string.
458 * @param localName The local name (without prefix), or empty string if not namespace processing.
459 *
460 * @return The element processor that matches the arguments, or null.
461 */
462 XSLTElementProcessor getProcessorFor(String uri, String localName)
463 {
464
465 XSLTElementProcessor elemDef = null; // return value
466
467 if (null == m_elements)
468 return null;
469
470 int n = m_elements.length;
471 int order = -1;
472 boolean multiAllowed = true;
473 for (int i = 0; i < n; i++)
474 {
475 XSLTElementDef def = m_elements[i];
476
477 // A "*" signals that the element allows literal result
478 // elements, so just assign the def, and continue to
479 // see if anything else matches.
480 if (def.m_name.equals("*"))
481 {
482
483 // Don't allow xsl elements
484 if (!equalsMayBeNullOrZeroLen(uri, Constants.S_XSLNAMESPACEURL))
485 {
486 elemDef = def.m_elementProcessor;
487 order = def.getOrder();
488 multiAllowed = def.getMultiAllowed();
489 }
490 }
491 else if (def.QNameEquals(uri, localName))
492 {
493 if (def.getRequired())
494 this.setRequiredFound(def.getName(), true);
495 order = def.getOrder();
496 multiAllowed = def.getMultiAllowed();
497 elemDef = def.m_elementProcessor;
498 break;
499 }
500 }
501
502 if (elemDef != null && this.isOrdered())
503 {
504 int lastOrder = getLastOrder();
505 if (order > lastOrder)
506 setLastOrder(order);
507 else if (order == lastOrder && !multiAllowed)
508 {
509 return null;
510 }
511 else if (order < lastOrder && order > 0)
512 {
513 return null;
514 }
515 }
516
517 return elemDef;
518 }
519
520 /**
521 * Given an unknown element, get the processor
522 * for the element.
523 *
524 * @param uri The Namespace URI, or an empty string.
525 * @param localName The local name (without prefix), or empty string if not namespace processing.
526 *
527 * @return normally a {@link ProcessorUnknown} reference.
528 * @see ProcessorUnknown
529 */
530 XSLTElementProcessor getProcessorForUnknown(String uri, String localName)
531 {
532
533 // XSLTElementProcessor lreDef = null; // return value
534 if (null == m_elements)
535 return null;
536
537 int n = m_elements.length;
538
539 for (int i = 0; i < n; i++)
540 {
541 XSLTElementDef def = m_elements[i];
542
543 if (def.m_name.equals("unknown") && uri.length() > 0)
544 {
545 return def.m_elementProcessor;
546 }
547 }
548
549 return null;
550 }
551
552 /**
553 * The allowed attributes for this type.
554 */
555 private XSLTAttributeDef[] m_attributes;
556
557 /**
558 * Get the allowed attributes for this type.
559 *
560 * @return An array of allowed attribute defs, or null.
561 */
562 XSLTAttributeDef[] getAttributes()
563 {
564 return m_attributes;
565 }
566
567 /**
568 * Given a namespace URI, and a local name, return the element's
569 * attribute definition, if it has one.
570 *
571 * @param uri The Namespace URI, or an empty string.
572 * @param localName The local name (without prefix), or empty string if not namespace processing.
573 *
574 * @return The attribute def that matches the arguments, or null.
575 */
576 XSLTAttributeDef getAttributeDef(String uri, String localName)
577 {
578
579 XSLTAttributeDef defaultDef = null;
580 XSLTAttributeDef[] attrDefs = getAttributes();
581 int nAttrDefs = attrDefs.length;
582
583 for (int k = 0; k < nAttrDefs; k++)
584 {
585 XSLTAttributeDef attrDef = attrDefs[k];
586 String uriDef = attrDef.getNamespace();
587 String nameDef = attrDef.getName();
588
589 if (nameDef.equals("*") && (equalsMayBeNullOrZeroLen(uri, uriDef) ||
590 (uriDef != null && uriDef.equals("*") && uri!=null && uri.length() > 0 )))
591 {
592 return attrDef;
593 }
594 else if (nameDef.equals("*") && (uriDef == null))
595 {
596
597 // In this case, all attributes are legal, so return
598 // this as the last resort.
599 defaultDef = attrDef;
600 }
601 else if (equalsMayBeNullOrZeroLen(uri, uriDef)
602 && localName.equals(nameDef))
603 {
604 return attrDef;
605 }
606 }
607
608 if (null == defaultDef)
609 {
610 if (uri.length() > 0 && !equalsMayBeNullOrZeroLen(uri, Constants.S_XSLNAMESPACEURL))
611 {
612 return XSLTAttributeDef.m_foreignAttr;
613 }
614 }
615
616 return defaultDef;
617 }
618
619 /**
620 * If non-null, the ContentHandler/TransformerFactory for this element.
621 */
622 private XSLTElementProcessor m_elementProcessor;
623
624 /**
625 * Return the XSLTElementProcessor for this element.
626 *
627 * @return The element processor for this element.
628 * @xsl.usage internal
629 */
630 public XSLTElementProcessor getElementProcessor()
631 {
632 return m_elementProcessor;
633 }
634
635 /**
636 * Set the XSLTElementProcessor for this element.
637 *
638 * @param handler The element processor for this element.
639 * @xsl.usage internal
640 */
641 public void setElementProcessor(XSLTElementProcessor handler)
642 {
643
644 if (handler != null)
645 {
646 m_elementProcessor = handler;
647
648 m_elementProcessor.setElemDef(this);
649 }
650 }
651
652 /**
653 * If non-null, the class object that should in instantiated for
654 * a Xalan instance of this element.
655 */
656 private Class m_classObject;
657
658 /**
659 * Return the class object that should in instantiated for
660 * a Xalan instance of this element.
661 *
662 * @return The class of the object that this element def should produce, or null.
663 */
664 Class getClassObject()
665 {
666 return m_classObject;
667 }
668
669 /**
670 * If true, this has a required element.
671 */
672 private boolean m_has_required = false;
673
674 /**
675 * Get whether or not this has a required element.
676 *
677 * @return true if this this has a required element.
678 */
679 boolean hasRequired()
680 {
681 return m_has_required;
682 }
683
684 /**
685 * If true, this is a required element.
686 */
687 private boolean m_required = false;
688
689 /**
690 * Get whether or not this is a required element.
691 *
692 * @return true if this is a required element.
693 */
694 boolean getRequired()
695 {
696 return m_required;
697 }
698
699 Hashtable m_requiredFound;
700
701 /**
702 * Set this required element found.
703 *
704 */
705 void setRequiredFound(String elem, boolean found)
706 {
707 if (m_requiredFound.get(elem) != null)
708 m_requiredFound.remove(elem);
709 }
710
711 /**
712 * Get whether all required elements were found.
713 *
714 * @return true if all required elements were found.
715 */
716 boolean getRequiredFound()
717 {
718 if (m_requiredFound == null)
719 return true;
720 return m_requiredFound.isEmpty();
721 }
722
723 /**
724 * Get required elements that were not found.
725 *
726 * @return required elements that were not found.
727 */
728 String getRequiredElem()
729 {
730 if (m_requiredFound == null)
731 return null;
732 Enumeration elems = m_requiredFound.elements();
733 String s = "";
734 boolean first = true;
735 while (elems.hasMoreElements())
736 {
737 if (first)
738 first = false;
739 else
740 s = s + ", ";
741 s = s + (String)elems.nextElement();
742 }
743 return s;
744 }
745
746 boolean m_isOrdered = false;
747
748 /**
749 * Get whether this element requires ordered children.
750 *
751 * @return true if this element requires ordered children.
752 */
753 boolean isOrdered()
754 {
755 /*if (!m_CheckedOrdered)
756 {
757 m_CheckedOrdered = true;
758 m_isOrdered = false;
759 if (null == m_elements)
760 return false;
761
762 int n = m_elements.length;
763
764 for (int i = 0; i < n; i++)
765 {
766 if (m_elements[i].getOrder() > 0)
767 {
768 m_isOrdered = true;
769 return true;
770 }
771 }
772 return false;
773 }
774 else*/
775 return m_isOrdered;
776 }
777
778 /**
779 * the order that this element should appear, or -1 if not ordered
780 */
781 private int m_order = -1;
782
783 /**
784 * Get the order that this element should appear .
785 *
786 * @return the order that this element should appear.
787 */
788 int getOrder()
789 {
790 return m_order;
791 }
792
793 /**
794 * the highest order of child elements have appeared so far,
795 * or -1 if not ordered
796 */
797 private int m_lastOrder = -1;
798
799 /**
800 * Get the highest order of child elements have appeared so far .
801 *
802 * @return the highest order of child elements have appeared so far.
803 */
804 int getLastOrder()
805 {
806 return m_lastOrder;
807 }
808
809 /**
810 * Set the highest order of child elements have appeared so far .
811 *
812 * @param order the highest order of child elements have appeared so far.
813 */
814 void setLastOrder(int order)
815 {
816 m_lastOrder = order ;
817 }
818
819 /**
820 * True if this element can appear multiple times
821 */
822 private boolean m_multiAllowed = true;
823
824 /**
825 * Get whether this element can appear multiple times
826 *
827 * @return true if this element can appear multiple times
828 */
829 boolean getMultiAllowed()
830 {
831 return m_multiAllowed;
832 }
833 }