diff --git a/src/org/opencms/xml/A_CmsXmlDocument.java b/src/org/opencms/xml/A_CmsXmlDocument.java index 49cf4baa7d4..758d2ece7d4 100644 --- a/src/org/opencms/xml/A_CmsXmlDocument.java +++ b/src/org/opencms/xml/A_CmsXmlDocument.java @@ -284,40 +284,23 @@ public CmsFile correctXmlStructure(CmsObject cms) throws CmsXmlException { // step 1: first sort the nodes according to the schema, this takes care of re-ordered elements List> nodeLists = new ArrayList>(); - for (I_CmsXmlSchemaType type : cd.getTypeSequence()) { - List elements = CmsXmlGenericWrapper.elements(root, type.getName()); - int maxOccures = cd.getChoiceMaxOccurs() > 0 - ? cd.getChoiceMaxOccurs() - : type.getMaxOccurs(); - if (elements.size() > maxOccures) { - if (type.getTypeName().equals(CmsXmlCategoryValue.TYPE_NAME)) { - if (type.getMaxOccurs() == 1) { - Element category = elements.get(0); - List categories = new ArrayList(); - for (Element value : elements) { - @SuppressWarnings("unchecked") - Iterator itLink = value.elementIterator(); - while (itLink.hasNext()) { - Element link = itLink.next(); - categories.add((Element)link.clone()); - } - } - category.clearContent(); - for (Element value : categories) { - category.add(value); - } - } + boolean isMultipleChoice = cd.getSequenceType() == CmsXmlContentDefinition.SequenceType.MULTIPLE_CHOICE; - } - - // to many nodes of this type appear according to the current schema definition - for (int lo = (elements.size() - 1); lo >= type.getMaxOccurs(); lo--) { - elements.remove(lo); - } - - } + // if it's a multiple choice element, the child elements must not be sorted into their types, + // but must keep their original order + if (isMultipleChoice) { + List elements = CmsXmlGenericWrapper.elements(root); + checkMaxOccurs(elements, cd.getChoiceMaxOccurs(), cd.getTypeName()); nodeLists.add(elements); } + // if it's a sequence, the children are sorted according to the sequence type definition + else { + for (I_CmsXmlSchemaType type : cd.getTypeSequence()) { + List elements = CmsXmlGenericWrapper.elements(root, type.getName()); + checkMaxOccurs(elements, type.getMaxOccurs(), type.getTypeName()); + nodeLists.add(elements); + } + } // step 2: clear the list of nodes (this will remove all invalid nodes) List nodeList = CmsXmlGenericWrapper.elements(root); @@ -345,6 +328,40 @@ public CmsFile correctXmlStructure(CmsObject cms) throws CmsXmlException { return m_file; } + /** + * Removes all nodes that exceed newly defined maxOccurs rules from the list of elements + * @param cd the content type definition + * @param maxOccurs maximum number of elements allowed + * @param typeName name of the element type + */ + private void checkMaxOccurs(List elements, int maxOccurs, String typeName) { + if (elements.size() > maxOccurs) { + if (typeName.equals(CmsXmlCategoryValue.TYPE_NAME)) { + if (maxOccurs == 1) { + Element category = elements.get(0); + List categories = new ArrayList(); + for (Element value : elements) { + @SuppressWarnings("unchecked") + Iterator itLink = value.elementIterator(); + while (itLink.hasNext()) { + Element link = itLink.next(); + categories.add((Element)link.clone()); + } + } + category.clearContent(); + for (Element value : categories) { + category.add(value); + } + } + } + + // too many nodes of this type appear according to the current schema definition + for (int lo = (elements.size() - 1); lo >= maxOccurs; lo--) { + elements.remove(lo); + } + } + } + /** * @see org.opencms.xml.I_CmsXmlDocument#getBestMatchingLocale(java.util.Locale) */