docs: @Override
      public void startElement(final String uri, final String localName, final String qName, final Attributes atts)
              throws SAXException {
          final String cls = atts.getValue(ATTRIBUTE_NAME_CLASS);
          final String id = atts.getValue(ATTRIBUTE_NAME_ID);
          final AttributesImpl attsMod = new AttributesImpl(atts);
          final String xmlLang = atts.getValue(ATTRIBUTE_NAME_XML_LANG);
          final String currentLang;
  
  
          if (skip && skipLevel > 0) {
              skipLevel++;
          }
  
          if (xmlLang != null) {
              currentLang = xmlLang;
          } else if (!lang.isEmpty()) {
              currentLang = lang.peek();
          } else {
              currentLang = null;
          }
          lang.push(currentLang);
  
          try {
              if (TOPIC_TOPIC.matches(cls)) {
                  topicSpecSet.add(qName);
  
                  if (include && !CHUNK_SELECT_TOPIC.equals(selectMethod)) {
                      // chunk="by-topic" and next topic element found
                      outputStack.push(output);
                      outputFileNameStack.push(outputFile);
  
                      outputFile = generateOutputFilename(id);
                      output = new OutputStreamWriter(new FileOutputStream(new File(outputFile)), StandardCharsets.UTF_8);
  
                      if (atts.getIndex(ATTRIBUTE_NAME_XML_LANG) < 0 && currentLang != null) {
                          attsMod.addAttribute("", ATTRIBUTE_NAME_LANG, ATTRIBUTE_NAME_XML_LANG, "CDATA", currentLang );
                      }
  //                    final FileInfo fi = generateFileInfo(outputFile);
  //                    job.add(fi);
  
                      changeTable.put(outputFile, outputFile);
                      if (id != null) {
                          changeTable.put(setFragment(currentParsingFile, id), setFragment(outputFile, id));
                      } else {
                          changeTable.put(currentParsingFile, outputFile);
                      }
  
                      // write xml header and workdir PI to the new generated file
                      writeStartDocument(output);
                      if (!OS_NAME.toLowerCase().contains(OS_NAME_WINDOWS)) {
                          writeProcessingInstruction(output, PI_WORKDIR_TARGET, new File(currentFile).getParentFile().getAbsolutePath());
                      } else {
                          writeProcessingInstruction(output, PI_WORKDIR_TARGET, UNIX_SEPARATOR + currentFile.resolve("."));
                      }
                      writeProcessingInstruction(output, PI_WORKDIR_TARGET_URI, currentFile.resolve(".").toString());
  
                      // create a new child element in separate case topicref is equals to parameter
                      // element in separateChunk(Element element)
                      final Element newTopicref = rootTopicref.getOwnerDocument().createElement(MAP_TOPICREF.localName);
                      newTopicref.setAttribute(ATTRIBUTE_NAME_CLASS, MAP_TOPICREF.toString());
                      newTopicref.setAttribute(ATTRIBUTE_NAME_XTRF, ATTR_XTRF_VALUE_GENERATED);
                      newTopicref.setAttribute(ATTRIBUTE_NAME_HREF, getRelativePath(currentFile.resolve(FILE_NAME_STUB_DITAMAP), outputFile).toString());
  
                      final Element topic = searchForNode(topicDoc, id, ATTRIBUTE_NAME_ID, TOPIC_TOPIC);
                      final Element topicmeta = createTopicMeta(topic);
                      newTopicref.appendChild(topicmeta);
  
                      if (stub != null) {
                          if (includelevel == 0 && siblingStub != null) {
                              // if it is the following sibling topic to the first topic in ditabase
                              // The first topic will not enter the logic at here because when meeting
                              // with first topic in ditabase, the include value is false
                              siblingStub.getParentNode().insertBefore(newTopicref, siblingStub);
                          } else {
                              stub.getParentNode().insertBefore(newTopicref, stub);
                          }
                          stubStack.push(stub);
                          stub = (Element) stub.cloneNode(false);
                          newTopicref.appendChild(stub);
                      }
                  }
  
                  processSelect(id);
              }
  
              if (include) {
                  includelevel++;
                  final Attributes resAtts = processAttributes(attsMod);
                  writeStartElement(output, qName, resAtts);
              }
          } catch (final IOException e) {
              logger.error(e.getMessage(), e);
          }
      }