Esempio n. 1
0
        // ======================== Getters and setters =======================================

        // ======================== Public methods ============================================

        /* -------------------------------------------------------------------------------------
        * Name:        ConvertOneOpsToFolia
        * Goal:        Convert one opensubtitle gz file to a folia.xml file
        * Parameters:  sFileIn     - File to be processed
        *              sDirIn      - Directory under which the input files are located
        *              sDirOut     - Directory where the output files should come
        *              bForce      - Create result, even though it exists already
        *              bMulti      - Only do multi-part files
        *              bIsDebug    - Debugging mode on or off
        * History:
        * 27/jan/2016 ERK Created
        *  ------------------------------------------------------------------------------------- */
        public bool ConvertOneOpsToFolia(String sFileIn, String sDirIn, String sDirOut, bool bForce,
                                         bool bMulti, bool bIsDebug)
        {
            // XmlReader rdOps = null;
            XmlWriter   wrFolia  = null;
            List <Sent> lSentBuf = new List <Sent>(); // Buffer containing sentences and words

            try {
                // Validate
                if (!File.Exists(sFileIn))
                {
                    return(false);
                }
                if (!Directory.Exists(sDirOut))
                {
                    return(false);
                }

                // If the input file cannot be read, then skip it
                if (!util.General.CanReadFile(sFileIn))
                {
                    return(true);
                }

                // Make sure dirout does not contain a trailing /
                if (sDirOut.EndsWith("/") || sDirOut.EndsWith("\\"))
                {
                    sDirOut = sDirOut.Substring(0, sDirOut.Length - 1);
                }

                // Retrieve the idmovie and the movie's name from the file name
                String sIdMovie = ""; String sMovieName = ""; String sMovieYear = "";
                if (!getMovieNameId(sFileIn, ref sMovieName, ref sIdMovie, ref sMovieYear))
                {
                    return(false);
                }

                // Get the destination directory
                String sDst    = sDirOut + "/" + sFileIn.Substring(sDirIn.Length + 1);
                String sDstDir = Path.GetDirectoryName(sDst);
                // Check existence of destination directory
                if (!Directory.Exists(sDstDir))
                {
                    Directory.CreateDirectory(sDstDir);
                }

                // Create a destination file name inside [sDirOut]
                String sFileName = Path.GetFileNameWithoutExtension(sFileIn);
                string sFileBase = Path.GetFullPath(Path.GetDirectoryName(sFileIn) + "/" + Path.GetFileName(sFileIn));
                String sBare     = sFileName;
                int    iUs       = sBare.IndexOf('_');
                int    iVersion  = 1; // Default version number
                int    iMax      = 1; // Maximum version number
                int    iSubtitle = 0; // Default subtitles.org number
                if (iUs >= 0)
                {
                    sBare = sBare.Substring(0, iUs);
                    // Get to the second part
                    String sSecond = sFileName.Substring(iUs + 1);
                    // Find two numbers there
                    Match mcOne = Regex.Match(sSecond, "\\d+");
                    if (!mcOne.Success)
                    {
                        errHandle.DoError("ConvertOneOpsToFolia", "cannot get number from [" + sSecond + "]");
                        return(false);
                    }
                    // Get first number
                    iVersion = Convert.ToInt32(mcOne.Value);
                    // Go to next number
                    mcOne = mcOne.NextMatch();
                    if (!mcOne.Success)
                    {
                        errHandle.DoError("ConvertOneOpsToFolia", "cannot get number from [" + sSecond + "]");
                        return(false);
                    }
                    iMax = Convert.ToInt32(mcOne.Value);

                    /*
                     * iVersion = Convert.ToInt32(sFileName.Substring(iUs + 1, 1));
                     * iMax = Convert.ToInt32(sFileName.Substring(iUs + 4, 1));
                     */
                }

                // Check if we need to continue
                if (bMulti && iMax == 1)
                {
                    debug("Skipping (non-multi): " + sFileIn);
                    return(true);
                }

                UInt64 iNumber;
                if (UInt64.TryParse(sBare, out iNumber))
                {
                    iSubtitle = Convert.ToInt32(iNumber);
                    sBare     = "S-O_" + iNumber.ToString("D8");
                }
                else
                {
                    sBare = "S-O_" + sBare;
                }
                // sBare = "S-O_" + string.Format("00000000", ((int) sBare));
                String sDstBare = Path.GetFullPath(sDstDir + "/" + sBare);
                // String sFileTmp = Path.GetFullPath(sDstBare + ".xml");
                String sFileOut  = Path.GetFullPath(sDstBare + ".folia.xml");
                String sFileOutZ = Path.GetFullPath(sDstBare + ".folia.xml.gz");

                // Check if output file already exists
                if (!bForce && File.Exists(sFileOutZ))
                {
                    debug("Skipping existing: " + sFileIn);
                    return(true);
                }

                // Other initialisations before the conversion starts
                OpsToFolia objOpsFolia = new OpsToFolia(errHandle);
                // objOpsFolia.setCurrentSrcFile(sFileTmp);
                objOpsFolia.setCurrentSrcFile("");
                int iSentNum = 0;
                // Set up an XML writer according to our liking
                XmlWriterSettings wrSet = new XmlWriterSettings();
                wrSet.Indent            = true;
                wrSet.NewLineHandling   = NewLineHandling.Replace;
                wrSet.NamespaceHandling = NamespaceHandling.OmitDuplicates;
                wrSet.ConformanceLevel  = ConformanceLevel.Document;

                /*
                 * // DOuble check to see if the conversion was already done
                 * if (!bForce && File.Exists(sFileOut) && !File.Exists(sFileTmp)) return true;
                 * // If this is a different version, and we already have a copy, then skip it
                 * if (iVersion > 1 && File.Exists(sFileOut) && !File.Exists(sFileTmp)) return true;
                 * */

                // Create a temporary folia output file with the bare essentials
                String sFileTmpF = sFileOut + ".tmp";
                // Bare folia text
                String sBareFolia = objOpsFolia.getIntro(sBare, sIdMovie, "", sMovieYear, iSubtitle, iVersion, iMax) +
                                    objOpsFolia.getExtro();
                // Write this text to a file
                XmlDocument pdxBareF = new XmlDocument();
                try {
                    pdxBareF.LoadXml(sBareFolia);
                } catch (Exception ex) {
                    errHandle.DoError("ConvertOneOpsToFolia/BareFolia problem", ex); // Provide standard error message
                    return(false);
                }
                // Adapt the moviename
                XmlNamespaceManager nsBare = new XmlNamespaceManager(pdxBareF.NameTable);
                nsBare.AddNamespace("b", pdxBareF.DocumentElement.NamespaceURI);
                XmlNode ndxMvName = pdxBareF.SelectSingleNode("./descendant::b:meta[@id='name']", nsBare);
                if (ndxMvName != null)
                {
                    ndxMvName.InnerText = sMovieName;
                }
                pdxBareF.Save(sFileTmpF);
                // Don't need objOpsFolia anymore
                objOpsFolia = null;

                // Convert the temporary files to the output file
                // (1) Open the input file
                debug("Starting: " + sFileIn);

                // (2) Make sure we have a 'global' start and finish time
                String sTimeStart = ""; String sTimeEnd = "";
                String sTimeBkup = "";    // Backup time for when we get confused
                String sLineSrt  = "";    // Line number within the SRT file
                bool   bStart    = false; // This word has the time-start marker
                bool   bEnd      = false; // This word has the time-end marker

                // Determine the file name template we will be looking for
                String sFileInTemplate = sFileName.Replace("1of" + iMax, "*of" + iMax) + ".gz";
                // Get all the files fulfilling this template
                String[] arFileIn = Directory.GetFiles(Path.GetDirectoryName(sFileIn), sFileInTemplate, SearchOption.TopDirectoryOnly);
                // Make sure the files are sorted correctly
                List <String> lFileIn = arFileIn.ToList <String>();
                lFileIn.Sort();
                int iFile = 0; // Number of the file from the [lFileIn] list

                // Skip those that do not have the correct number of parts
                if (iMax != lFileIn.Count)
                {
                    debug("--Part/Count mismatch");
                    return(true);
                }

                // (3) Open the bare FoLiA file for input
                using (StreamReader rdFileTmpF = new StreamReader(sFileTmpF))
                    using (XmlReader rdFolia = XmlReader.Create(rdFileTmpF))

                        // (5) Create an output file
                        // using (StreamWriter wrFileTmpOut = new StreamWriter(sFileOut))
                        //  using (wrFolia = XmlWriter.Create(wrFileTmpOut, wrSet)) {
                        using (wrFolia = new FoliaXmlWriter(sFileOut, Encoding.UTF8)) {
                            // (6) Walk through the bare folia input file
                            while (!rdFolia.EOF && rdFolia.Read())
                            {
                                // (7) Check what kind of input this is
                                // Note: we need to pause after reading the <p> start element
                                if (rdFolia.IsStartElement("p"))
                                {
                                    // (8) Do make sure that we WRITE the start element away
                                    WriteShallowNode(rdFolia, wrFolia);

                                    // Check the index
                                    if (iFile < 0 || iFile >= lFileIn.Count)
                                    {
                                        // Cannot do this
                                        errHandle.DoError("ConvertOneOpsToFolia", "iFile=" + iFile + " but lFileIn=" + lFileIn.Count);
                                    }
                                    // Retrieve the next input file from the list
                                    String sFileTmp = lFileIn[iFile].Replace(".xml.gz", "xml");
                                    // Unzip the file
                                    if (!util.General.DecompressFile(lFileIn[iFile], sFileTmp))
                                    {
                                        return(false);
                                    }

                                    // Increment the file number for the next run and reset the sentence number
                                    iFile += 1; iSentNum = 0;

                                    // (4) Open the open-subtitle xml file for input
                                    using (StreamReader rdFileTmp = new StreamReader(sFileTmp))
                                        using (XmlReader rdOps = XmlReader.Create(rdFileTmp)) {
                                            // (9) Walk through the *actual* open-subtitle input file
                                            while (!rdOps.EOF && rdOps.Read())
                                            {
                                                // (10) Check what this is
                                                if (rdOps.IsStartElement("s"))
                                                {
                                                    // Read the <s> element as one string
                                                    String sWholeS = rdOps.ReadOuterXml();
                                                    iSentNum++;
                                                    // Process the <s> element:
                                                    // (1) put it into an XmlDocument
                                                    XmlDocument pdxSrc = new XmlDocument();
                                                    pdxSrc.LoadXml(sWholeS);
                                                    // (2) Create a namespace mapping for the opensubtitles *source* xml document
                                                    XmlNamespaceManager nsOps = new XmlNamespaceManager(pdxSrc.NameTable);
                                                    nsOps.AddNamespace("df", pdxSrc.DocumentElement.NamespaceURI);
                                                    // (3) Create a sentence identifier
                                                    String sSentId = sBare + ".p." + iFile + ".s." + iSentNum;
                                                    // (4) The first <s> should at least have some <w> elements
                                                    if (iSentNum == 1)
                                                    {
                                                        // Check out first sentence
                                                        if (pdxSrc.SelectSingleNode("./descendant::df:w", nsOps) == null)
                                                        {
                                                            // Skip this file -- it contains RAW info, no <w> elements
                                                            return(true);
                                                        }
                                                    }
                                                    // (5) Create a new sentence in the buffer
                                                    Sent oSent = new Sent(sSentId);
                                                    lSentBuf.Add(oSent);
                                                    // (6) Process all *descendants* of this <s> one-by-one
                                                    XmlNodeList ndChild = pdxSrc.SelectNodes("./descendant-or-self::df:s/descendant::df:*", nsOps);
                                                    int         iWord   = 0;
                                                    for (int i = 0; i < ndChild.Count; i++)
                                                    {
                                                        // Get this child
                                                        XmlNode ndThis = ndChild.Item(i);
                                                        // Action depends on the type of child this is
                                                        switch (ndThis.Name)
                                                        {
                                                        case "time":
                                                            // Get the time id and value
                                                            String sTimeId  = ndThis.Attributes["id"].Value;
                                                            String sTimeVal = ndThis.Attributes["value"].Value;
                                                            // Is this the *start* or *end* time?
                                                            if (sTimeId.EndsWith("S"))
                                                            {
                                                                // Keep track of the latest *start* time and reset the end time
                                                                sTimeStart = sTimeVal; sTimeEnd = ""; bStart = true;
                                                                sTimeBkup  = sTimeVal;
                                                                // Get the SRT line number
                                                                sLineSrt = sTimeId.Substring(1, sTimeId.Length - 2);
                                                            }
                                                            else
                                                            {
                                                                // Add the end-time
                                                                sTimeEnd = sTimeVal;
                                                                // Reset the starting time
                                                                sTimeStart = "";
                                                                bEnd       = true;
                                                                if (bEnd)
                                                                {
                                                                    // Reset flag
                                                                    bEnd = false;
                                                                    // Add mark for starting
                                                                    lSentBuf[lSentBuf.Count - 1].markEnd();
                                                                }
                                                                // Process the sentence buffer
                                                                // (a) Process all previous sentences
                                                                int iCount = lSentBuf.Count;
                                                                if (!FlushOpsToFolia(ref lSentBuf, ref wrFolia, iCount - 1, sTimeEnd, sTimeBkup))
                                                                {
                                                                    return(false);
                                                                }
                                                                // (b) Process the words in the current sentence
                                                                List <WordBuf> lCurrent = lSentBuf[lSentBuf.Count - 1].words;
                                                                for (int j = 0; j < lCurrent.Count; j++)
                                                                {
                                                                    // Check if this word needs to have an end-time
                                                                    if (lCurrent[j].e == "")
                                                                    {
                                                                        lCurrent[j].e = sTimeEnd;
                                                                    }
                                                                }
                                                            }
                                                            break;

                                                        case "i": // Some have an <i> tag to indicate what goes on one line: ignore
                                                            break;

                                                        case "w":
                                                            // Process this word
                                                            iWord++;
                                                            // Get the text of this word
                                                            String sWord = ndThis.InnerText;
                                                            // Create an identifier for this word
                                                            // String sWordId = sSentId + ".w." + iWord;
                                                            String sWordCl = (util.General.DoLike(sWord, ".|,|...|..|-|?|!|\"|'|:|;|(|)")) ? "Punct" : "Vern";
                                                            // Add this word to the buffer of this current sentence
                                                            lSentBuf[lSentBuf.Count - 1].addWord(sWord, sWordCl);
                                                            // Add the start-time to this word
                                                            lSentBuf[lSentBuf.Count - 1].addStart(sTimeStart);
                                                            // Add the SRT number to this word
                                                            lSentBuf[lSentBuf.Count - 1].addLine(sLineSrt);
                                                            if (bStart)
                                                            {
                                                                // Reset flag
                                                                bStart = false;
                                                                // Add mark for starting
                                                                lSentBuf[lSentBuf.Count - 1].markStart();
                                                            }

                                                            break;

                                                        default:
                                                            // No idea what to do here -- just skip??
                                                            break;
                                                        }
                                                    }
                                                }
                                            } // End while
                                            // Process any remaining sentences
                                            if (!FlushOpsToFolia(ref lSentBuf, ref wrFolia, lSentBuf.Count, sTimeEnd, sTimeBkup))
                                            {
                                                return(false);
                                            }
                                            rdOps.Close(); // rdOps.Dispose();
                                            rdFileTmp.Close();
                                            // Remove the temporary file
                                            File.Delete(sFileTmp);
                                        }

                                    // }
                                }
                                else
                                {
                                    // Process reading the input
                                    WriteShallowNode(rdFolia, wrFolia);
                                }
                            }
                            // debug("Point 3: locked = " + util.General.IsFileLocked(sFileTmp));
                            wrFolia.Flush();
                            wrFolia.Close(); // wrFolia.Dispose();
                            rdFolia.Close(); // rdFolia.Dispose();
                            rdFileTmpF.Close();
                            // debug("Point 4: locked = " + util.General.IsFileLocked(sFileTmp));
                        }

                // Remove the temporary Folia file
                File.Delete(sFileTmpF);

                // Convert to compressed-file
                if (!util.General.CompressFile(sFileOut, sFileOutZ))
                {
                    return(false);
                }
                // Remove the original output
                File.Delete(sFileOut);

                // Return positively
                return(true);
            } catch (Exception ex) {
                errHandle.DoError("ConvertOneOpsToFolia", ex); // Provide standard error message
                return(false);

                throw;
            }
        }
Esempio n. 2
0
        // ============================================================================================
        /* -------------------------------------------------------------------------------------
         * Name:        ConvertOneEngToFolia
         * Goal:        Create a .folia.xml file with metadata for the indicated input file
         *              Note: the .cmdi file will be placed in the same directory as FileIn
         * Parameters:  sFileIn     - File to be processed
         *              bForce      - Create result, even though it exists already
         *              bIsDebug    - Debugging mode on or off
          * Note:        This is the XmlReader/XmlWriter implementation that works very fast
          *                under both Windows and Linux/MONO.
          *
         * History:
         * 1/feb/2016 ERK Created XmlDocument/XPath version
         * 7/mar/2016 ERK Started conversion to XmlReader version
           ------------------------------------------------------------------------------------- */
        public bool ConvertOneEngToFolia(XmlReader rdLinkGrp, bool bForce, bool bDebug)
        {
            String sFileCmdi = "";      // A .cmdi.xml file belonging to the Dutch .folia.xml file
              String sSubtitleIdNL = "";  // Dutch   open-subtitles subtitle id
              String sSubtitleIdEN = "";  // English open-subtitles subtitle id
              String sFileNL = "";        // Dutch subtitle .folia.xml file
              String sFileEn = "";        // English .folia.xml output file
              String sFileTr = "";        // A .folia.xml file that contains the translation in <complexalignments>
              String sFileTrGz = "";      // Translation file, but zipped
              String sName = "";          // Name we are currently dealing with

              try {
            // Validate
            if (rdLinkGrp == null) { errHandle.DoError("ConvertOneEngToFolia", "No linkGrp"); return false; }
            if (!Directory.Exists(sDirOutput)) { errHandle.DoError("ConvertOneEngToFolia", "No output directory"); return false; }

            // (1) Get the open subtitle id's
            sSubtitleIdNL = getMovieId(rdLinkGrp.GetAttribute("toDoc"));
            sSubtitleIdEN = getMovieId(rdLinkGrp.GetAttribute("fromDoc"));
            errHandle.Status("EngConv [" + sSubtitleIdEN + "/" + sSubtitleIdNL + "]");
            // ====================== DEBUG ==============
            if (sSubtitleIdNL == "23233") {
              int i = 0;
            }
            // ===========================================

            // (2) Find the Dutch .folia.xml.gz file (converted FoLiA format)
            sFileNL = getDutchFolia(sSubtitleIdNL);
            String sGzNL = getXmlGzFile(sFileNL, "nl");
            // If we don't have this input, then return empty-handed
            if (sGzNL == "") {
              errHandle.Status("EngConv 1: cannot find Dutch " + Path.GetFileNameWithoutExtension(sFileNL));
              return true;
            }

            // (3) Find the English .folia.xml.gz file (converted FoLiA format)
            sFileEn = getDutchFolia(sSubtitleIdEN);
            String sGzEN = getXmlGzFile(sFileEn, "en");
            // If we don't have this input, then return empty-handed
            if (sGzEN == "") {
              errHandle.Status("EngConv 2: cannot find English " + Path.GetFileNameWithoutExtension(sFileEn));
              return true;
            }

            sName = sFileEn.Replace(".folia.xml", "");
            String sNameNL = sFileNL.Replace(".folia.xml", "");

            // (4) Show what we are doing
            errHandle.Status("Process parallel between " + Path.GetFileNameWithoutExtension(sFileEn) +
              " and " + Path.GetFileNameWithoutExtension(sFileNL));

            // (5a) Re-initialize the lists of translations
            lstNl.Clear(); lstEn.Clear();

            // (5) Read the Dutch and the English folia.xml files (unpack + read)
            String sYear = "";
            if (!getTranslation(sGzNL, lstNl, ref sYear, true)) {errHandle.DoError("ConvertOneEngToFolia", "getTranslation NL problem"); return false;}
            if (!getTranslation(sGzEN, lstEn, ref sYear, false)) { errHandle.DoError("ConvertOneEngToFolia", "getTranslation EN problem"); return false; }

            // (6) Determine name of output folia.xml file
            String sDir = sDirOutput + sYear;
            if (!Directory.Exists(sDir)) Directory.CreateDirectory(sDir);
            sFileTr = sDir + "/S-OP_" + Convert.ToInt32(sSubtitleIdNL).ToString("D8") + ".folia.xml";
            sFileTrGz = sFileTr + ".gz";

            // (7) Check existence - skip if needed
            if (!bForce && (File.Exists(sFileTr) || File.Exists(sFileTrGz))) return true;

            // (7b) set the parallel at the first child node
            while (!rdLinkGrp.EOF && !rdLinkGrp.IsStartElement("link")) { rdLinkGrp.Read(); }
            // (8) Start reading the English and re-writing as translation FoLiA
            //         using (FoliaXmlWriter wrEN = new FoliaXmlWriter(sFileTr, Encoding.UTF8))
            //         using (XmlWriter wrEN = XmlWriter.Create(sFileTr, setWr)) {
            String sFileEng = sGzEN.Replace(".gz", "");
            using (StreamReader rdFileIn = new StreamReader(sFileEng))
            using (XmlReader rdFileXml = XmlReader.Create(rdFileIn, setThis))
            using (FoliaXmlWriter wrEN = new FoliaXmlWriter(sFileTr, Encoding.UTF8)) {
              // Read through the preamble of the English FoLiA and add my own annotation tag
              bool bAnnotDone = false;
              bool bMetaDone = false;
              while (!rdFileXml.EOF && (!bAnnotDone || !bMetaDone) && rdFileXml.Read()) {
            if (rdFileXml.IsStartElement("annotations")) {
              // Copy the <annotations> starting node content
              oTools.WriteShallowNode(rdFileXml, wrEN);
              // Read until (but not including) the end element
              while (!rdFileXml.EOF && !bAnnotDone && rdFileXml.Read()) {
                if (rdFileXml.NodeType == XmlNodeType.EndElement && rdFileXml.Name == "annotations") {
                  // Insert my own annotation comment here
                  XmlDocument pdxTmp = new XmlDocument();
                  oTools.SetXmlDocument(pdxTmp, "http://ilk.uvt.nl/folia");
                  oTools.AddXmlChild(null, "alignment-annotation",
                    "set", "trans", "attribute",
                    "annotator", "opsubeng", "attribute",
                    "annotatortype", "auto", "attribute",
                    "", "", "text");
                  wrEN.WriteNode(XmlReader.Create(new StringReader(pdxTmp.OuterXml)), true);
                  // Copy the <annotations> end node content
                  oTools.WriteShallowNode(rdFileXml, wrEN);
                  // Tell the world to continue
                  bAnnotDone = true;
                } else {
                  // Copy the <annotations> starting node content
                  oTools.WriteShallowNode(rdFileXml, wrEN);
                }
              }
            } else {
              // Test for metadata end
              if (rdFileXml.NodeType == XmlNodeType.EndElement && rdFileXml.Name == "metadata") bMetaDone = true;
              // Copy the content to the xml-writer output
              oTools.WriteShallowNode(rdFileXml, wrEN);
            }
              }
              // Double check: has annotation been processed
              if (!bAnnotDone || !bMetaDone) {
            errHandle.Status("ConvertOneEngToFolia problem: annotation has not been processed correctly: "+bAnnotDone+" "+bMetaDone);
            return false;
              }
              // Read and write until having finished reading the first <p> element
              bool bPstarted = false;
              while (!rdFileXml.EOF && !bPstarted && rdFileXml.Read()) {
            if (rdFileXml.IsStartElement("p")) bPstarted = true;
            // Copy the content to the xml-writer output
            oTools.WriteShallowNode(rdFileXml, wrEN);
              }
              //
              bool bHaveLink = rdLinkGrp.IsStartElement("link");
              bool bPfinish = false;
              // Loop through all <link> children of <linkGrp>
              while (!rdLinkGrp.EOF && bHaveLink && !rdFileXml.EOF) {
            // Read the parameters for this English-Dutch match
            String sXtargets = rdLinkGrp.GetAttribute("xtargets");
            // Be prepared: skip until the next start element (if there is any!!)
            while (!rdLinkGrp.EOF && rdLinkGrp.Read() && rdLinkGrp.NodeType != XmlNodeType.Element);
            // Set a flag to signal that the next one will be LINK
            bHaveLink = (!rdLinkGrp.EOF && rdLinkGrp.NodeType == XmlNodeType.Element && rdLinkGrp.Name == "link");
            // errHandle.Status("Processing: [" + sXtargets + "]");
            String[] arTargets = sXtargets.Split(';');
            if (arTargets.Length ==2) {
              // make arrays of the English source and Dutch destination
              String[] arSrcEN = arTargets[0].Trim().Split(' ');
              String[] arDstNL = arTargets[1].Trim().Split(' ');
              // Do we have an English source?
              if (arSrcEN.Length == 0 || arSrcEN[0] == "") {
                // There is no English source sentence specification
                // This means we can put the alignment anywhere
                // Get the appropriate translation code
                String sEnNl = "";
                if (!getTranslationCode(arSrcEN, arDstNL, sName, sNameNL, sFileNL, ref sEnNl)) {
                  errHandle.DoError("engConv/ConvertOneEngToFolia 0x0010", "No translation code");
                  return false;
                }
                try {
                  wrEN.WriteNode(XmlReader.Create(new StringReader(sEnNl), setThis), true);
                } catch (Exception ex) {
                  errHandle.DoError("engConv/ConvertOneEngToFolia 0x0011", ex);
                  return false;
                }
              } else {
                // Find the English source node
                String sIdEN = sName + ".p.1.s." + arSrcEN[arSrcEN.Length - 1];
                bool bCorrectS = false;
                // Read the English source until we reach this <s> node
                while (!rdFileXml.EOF && !bCorrectS && rdFileXml.Read()) {
                  // (2) Check the input element
                  if (rdFileXml.IsStartElement("s")) {
                    // Copy the <s> starting node content
                    oTools.WriteShallowNode(rdFileXml, wrEN);
                    // Check the ID of this element
                    String sId = rdFileXml.GetAttribute("xml:id");
                    // Check if this is the correct node and if we are able to PLACE it at this point
                    if (sId == sIdEN ) {
                      bCorrectS = true;   // Found the correct node
                      // Can we place it here?
                      if (bPfinish) {
                        // Unable to place the node here
                        errHandle.Status("Unable to output English id=" + sIdEN);
                      } else {
                        // Read <s> content until having processed the end-element
                        bool bEndOfS = false;
                        while (!rdFileXml.EOF && !bEndOfS && rdFileXml.Read()) {
                          // Make sure we skip the <w> elements
                          if (rdFileXml.IsStartElement("w")) {
                            // The <w> elements need to be skipped, so read through until the matching end-element
                            // rdFileXml.ReadToNextSibling("w");
                            rdFileXml.ReadOuterXml();
                          } else if (rdFileXml.NodeType == XmlNodeType.EndElement && rdFileXml.Name == "s") {
                            // Copy the output node
                            oTools.WriteShallowNode(rdFileXml, wrEN);
                            // Get the appropriate translation code
                            String sEnNl = "";
                            if (!getTranslationCode(arSrcEN, arDstNL, sName, sNameNL, sFileNL, ref sEnNl)) {
                              errHandle.DoError("ConvertOneEngToFolia", "getTranslation EN problem"); return false;
                            }
                            try {
                              wrEN.WriteNode(XmlReader.Create(new StringReader(sEnNl), setThis), true);
                            } catch (Exception ex) {
                              errHandle.DoError("engConv/ConvertOneEngToFolia 0x0012", ex);
                              return false;
                            }
                            // Signal this is the end of the s
                            bEndOfS = true;
                          } else {
                            // Copy input to output
                            oTools.WriteShallowNode(rdFileXml, wrEN);
                          }
                        }
                      }

                      int iStop = 1;
                    }
                  } else if (rdFileXml.IsStartElement("w")) {
                    // The <w> elements need to be skipped, so read through until the matching end-element
                    rdFileXml.ReadOuterXml();
                  } else if (rdFileXml.NodeType == XmlNodeType.EndElement && rdFileXml.Name == "p") {
                    // This is an ending </p>
                    // (1) Is a <link> still following?
                    if (bHaveLink) {
                      // Process links until we are through...
                      int iE = 3;
                    }
                    // (1) write it out
                    oTools.WriteShallowNode(rdFileXml, wrEN);
                    // (2) Warn the while-loop that this is a finishing </p> element
                    bPfinish = true;
                  } else {
                    // If there is another opening <p> we can reset the <p> finish
                    if (rdFileXml.IsStartElement("p")) bPfinish = false;
                    // Copy the content to the xml-writer output
                    oTools.WriteShallowNode(rdFileXml, wrEN);
                  }
                }
                // Check if </p> has been found
                if (bPfinish) {

                }
                // Check whether we found the correct S or not
                if (!bCorrectS) {
                  // Did not find the correct S -- skip through
                  int iMissed = 1;
                  errHandle.Status("Missing node "+ sIdEN);
                }
              }
            }
            // The next <link> is retrieved at the start of this loop
              }
            }
            // Zip the resulting .folia.xml file
            if (opsub.util.General.CompressFile(sFileTr, sFileTrGz)) {
              // If zipping was successful, then delete the file
              File.Delete(sFileTr);
            }

            return true;
              } catch (Exception ex) {
            errHandle.DoError("engConv/ConvertOneEngToFolia", ex);
            return false;
              }
        }