docs: public CmsFile correctXmlStructure(CmsObject cms) throws CmsXmlException {
  
          // apply XSD schema translation
          Attribute schema = m_document.getRootElement().attribute(
              I_CmsXmlSchemaType.XSI_NAMESPACE_ATTRIBUTE_NO_SCHEMA_LOCATION);
          if (schema != null) {
              String schemaLocation = schema.getValue();
              String translatedSchema = OpenCms.getResourceManager().getXsdTranslator().translateResource(schemaLocation);
              if (!schemaLocation.equals(translatedSchema)) {
                  schema.setValue(translatedSchema);
              }
          }
          updateLocaleNodeSorting();
  
          // iterate over all locales
          Iterator<Locale> i = m_locales.iterator();
          while (i.hasNext()) {
              Locale locale = i.next();
              List<String> names = getNames(locale);
              List<I_CmsXmlContentValue> validValues = new ArrayList<I_CmsXmlContentValue>();
  
              // iterate over all nodes per language
              Iterator<String> j = names.iterator();
              while (j.hasNext()) {
  
                  // this step is required for values that need a processing of their content
                  // an example for this is the HTML value that does link replacement
                  String name = j.next();
                  I_CmsXmlContentValue value = getValue(name, locale);
                  if (value.isSimpleType()) {
                      String content = value.getStringValue(cms);
                      value.setStringValue(cms, content);
                  }
  
                  // save valid elements for later check
                  validValues.add(value);
              }
  
              if (isAutoCorrectionEnabled()) {
                  // full correction of XML
                  if (validValues.size() < 1) {
                      // no valid element was in the content
                      if (hasLocale(locale)) {
                          // remove the old locale entirely, as there was no valid element
                          removeLocale(locale);
                      }
                      // add a new default locale, this will also generate the default XML as required
                      addLocale(cms, locale);
                  } else {
                      // there is at least one valid element in the content
  
                      List<Element> roots = new ArrayList<Element>();
                      List<CmsXmlContentDefinition> rootCds = new ArrayList<CmsXmlContentDefinition>();
                      List<Element> validElements = new ArrayList<Element>();
  
                      // gather all XML content definitions and their parent nodes
                      Iterator<I_CmsXmlContentValue> it = validValues.iterator();
                      while (it.hasNext()) {
                          // collect all root elements, also for the nested content definitions
                          I_CmsXmlContentValue value = it.next();
                          Element element = value.getElement();
                          validElements.add(element);
                          if (element.supportsParent()) {
                              // get the parent XML node
                              Element root = element.getParent();
                              if ((root != null) && !roots.contains(root)) {
                                  // this is a parent node we do not have already in our storage
                                  CmsXmlContentDefinition rcd = value.getContentDefinition();
                                  if (rcd != null) {
                                      // this value has a valid XML content definition
                                      roots.add(root);
                                      rootCds.add(rcd);
                                  } else {
                                      // no valid content definition for the XML value
                                      throw new CmsXmlException(
                                          Messages.get().container(
                                              Messages.ERR_CORRECT_NO_CONTENT_DEF_3,
                                              value.getName(),
                                              value.getTypeName(),
                                              value.getPath()));
                                  }
                              }
                          }
                      }
  
                      for (int le = 0; le < roots.size(); le++) {
                          // iterate all XML content root nodes and correct each XML subtree
  
                          Element root = roots.get(le);
                          CmsXmlContentDefinition cd = rootCds.get(le);
  
                          // step 1: first sort the nodes according to the schema, this takes care of re-ordered elements
                          List<List<Element>> nodeLists = new ArrayList<List<Element>>();
                          boolean isMultipleChoice = cd.getSequenceType() == CmsXmlContentDefinition.SequenceType.MULTIPLE_CHOICE;
  
                          // 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<Element> nodeList = new ArrayList<Element>();
                              List<Element> elements = CmsXmlGenericWrapper.elements(root);
                              Set<String> typeNames = cd.getSchemaTypes();
                              for (Element element : elements) {
                                  // check if the node type is still in the definition
                                  if (typeNames.contains(element.getName())) {
                                      nodeList.add(element);
                                  }
                              }
                              checkMaxOccurs(nodeList, cd.getChoiceMaxOccurs(), cd.getTypeName());
                              nodeLists.add(nodeList);
                          }
                          // if it's a sequence, the children are sorted according to the sequence type definition
                          else {
                              for (I_CmsXmlSchemaType type : cd.getTypeSequence()) {
                                  List<Element> 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<Element> nodeList = CmsXmlGenericWrapper.elements(root);
                          nodeList.clear();
                          Iterator<List<Element>> in = nodeLists.iterator();
                          while (in.hasNext()) {
                              // now add all valid nodes in the right order
                              List<Element> elements = in.next();
                              nodeList.addAll(elements);
                          }
  
                          // step 3: now append the missing elements according to the XML content definition
                          cd.addDefaultXml(cms, this, root, locale);
                      }
                  }
              }
              initDocument();
          }
  
          // write the modified XML back to the VFS file
          if (m_file != null) {
              // make sure the file object is available
              m_file.setContents(marshal());
          }
          return m_file;
      }