I have health documents which are currently in the hOCR format. I want to convert them to an xml format.

Is there a Mac/Linux - specific software which can do that?


A Mac/Linux/Windows specific software might exist, but I wrote my own PHP script to get all the data out of the hOCR file into a database, and from there I can create whatever format I want with the data.

hOCR should be xhtml already. The php script below reads the hOCR data file (produced by Tesseract OCR) word by word (with word data, like page, line, word nr, word itself, coordinates...) into a SQLite3 database, and from there I can do whatever I want with the data, like querying and insert it into some xml tags as required, or look for words from the next line with same starting x coordinates, etc.

The php code (5.4+) below contains a lot of unnecessary stuff like comments etc., but it reads the content of a hOCR file into a SQLite3 db file quite fast.

Depending on Your language (here mostly Finnish, ie. ISO-8859-15) You might want to change some of the regex etc. And the file name to be processed is given as the first argument to this script.

// Splitting a hOCR file to rows with page, area, line, word info per word in a doc
// Function to replace all separator chars on row with one thing, so that one explode per row will do

$dbh_hocr=new SQlite3("hOCRtemp.db");

$createTable=$dbh_hocr->exec("create table if not exists invWords (id INTEGER PRIMARY KEY, FileName TEXT, PageNr INTEGER, LineNr INTEGER, WordNr INTEGER, WordName TEXT, X1 INTEGER, Y1 INTEGER, X2 INTEGER, Y2 INTEGER)");
$clearTheTable=$dbh_hocr->exec("delete from invWords");

// The file name is in argv[1]

$pages=explode("<div class='ocr_page'", $fileToUse);
foreach($pages as $ocrCarea)
    $thisOcrCarea=explode("<div class='ocr_carea'", $ocrCarea);
    foreach($thisOcrCarea as $ocrPar)
        $thisOcrPar=explode("<div class='ocr_par'", $ocrPar);
        foreach($thisOcrPar as $ocrLine)
            $thisOcrLine=explode("<span class='ocr_line'", $ocrLine);
            foreach($thisOcrLine as $ocrWord)
                $thisOcrWord=explode("<span class='ocrx_word'", $ocrWord);
                foreach($thisOcrWord as $item)
                    if(substr_count($item, "block_")>0)
                    if(substr_count($item, "page_")>0)

                        $msg="Sivurivi ";

                        $thisItem=explode("page_", $item);
                        $thisPageNr=explode("'", $thisItem);
                        $pageItem=strip_tags($thisPageNr[0]); // Jeh. It works.

                    if(substr_count($item, "line_")>0)
                        $msg="Rivirivi ";
                        $thisLineItem=explode("line_", $item);
                        $thisLineNr=explode("'", $thisLineItem);
                    if(substr_count($item, "word_")>0)
                        $msg="Sanarivi ";
                        $thisWordItem=explode("word_", $item);
                        $thisWordNr=explode("'", $thisWordItem);
                        $lopRiv=explode("\"", $restOfRow);
                        $boxCoordsPart=explode(" ", $boxCoordsPart);
                        $theWordHere=strip_tags(substr($lopRiv[2], 1));
                            $theWordHere=trim(str_replace("\n", "", $theWordHere));
                            $theWordHere=str_replace("\n", "", $theWordHere);   
                        $theWordHere=iconv('UTF-8', 'ISO-8859-15', $theWordHere);
                        $theWordHere=preg_replace("/[^0-9A-ZÅÄÖa-zåäö\-\/, .]/", "", $theWordHere);
                        array_push($thisDocWords, $thisWordData);



$stmt=$dbh_hocr->prepare("insert into invWords (FileName, PageNr, LineNr, WordNr, WordName, X1, Y1, X2, Y2) values (:FileName, :PageNr, :LineNr, :WordNr, :WordName, :X1, :Y1, :X2, :Y2)");

foreach($thisDocWords as $thisWordRowArr)

    $thisWordRowArr=explode("#", $thisWordRowArr);

    $theFirstCharInWordName=substr(trim($wordName), 0, 1);
    if(!preg_match('/^[A-Za-zÅÄÖåäö0-9]/', $theFirstCharInWordName))
        $wordName=substr($wordName, 1);
    $theLastChar=substr($wordName, -1);

    if(!preg_match('/^[A-Za-zÅÄÖåäö0-9]/', $theLastChar))
        $wordName=substr($wordName, 0, $lengthOfWordNameToUse);

    if($lineNumber<15 && substr($wordName, 0, 7)=="VUOKRAA")


$stmt->bindValue(':FileName', $fileNameHere);
$stmt->bindValue(':PageNr', $pageNumber);
$stmt->bindValue(':LineNr', $lineNumber);
$stmt->bindValue(':WordNr', $wordNumber);
$stmt->bindValue(':WordName', $wordName);
$stmt->bindValue(':X1', $x1);
$stmt->bindValue(':Y1', $y1);
$stmt->bindValue(':X2', $x2);
$stmt->bindValue(':Y2', $y2);
    } // END FOREACH

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.