AfArcFileXmlTextRead

Aus ArcFlow Wiki
Zur Navigation springen Zur Suche springen
Diese Seite enthält Bearbeitungen, die nicht zum Übersetzen freigegeben sind.
 AfArcFileXmlTextRead(handle1, int2) : int

Nicht ausführbar von der APINicht ausführbar von der Programmierschnittstelle (DLL)Nicht ausführbar mit der Application Remote ControlAusführbar von der Script-API

Positionen des erkannten Textes
handle1 Deskriptor eines Memory-Objekts
int2 Seitennummer
Resultat int Fehlerwert
Siehe

Verwandte Befehle, AfArcFileMetaGet()

Mit der Funktion kann in einem Ereignis nach Texterkennung die Positionsinformationen zum erkannten Text eingelesen werden.

Bei der Verwendung des Office-Server der vorhergehenden Generation (Version 4.0.x), werden die Positionsinformationen nur dann erstellt, wenn in der Datei afocr.cfg die Einträge PdfRecognition=3 und OcrCreateXml=1 vorhanden sind.

Die Positionsinformationen stehen nur zur Verfügung, wenn eine Texterkennung durch die OCR-Software erfolgt und in den Einstellungen für den Datentyp die Einstellung "Text mit Position" aktiviert ist.

Im Parameter (int1) muss der Deskriptor eines zuvor mit AfMemAllocate() angelegten Memory-Objekts übergeben werden. In (int2) wird die Seitennummer angeben.

Nach erfolgreicher Ausführung der Anweisung befindet sich ein XML-Dokument im Memory-Objekt. Das Objekt kann mit der Anweisung XmlLoad() (siehe CONZEPT 16 Hilfe) in eine XML-Struktur überführt werden. Im folgenden Beispiel wird das Memory-Objekt in eine externe Datei geschrieben.

Beispiel:

tMemory # AfMemAllocate(_MemAutosize);
tMemory->spCharset # _CharSetUTF8;
tFile # FsiOpen('c:\temp\ocrtextpositions.xml',_FsiStdWrite);
tResult # AfArcFileXmlTextRead(tMemory,1);
tResult # FsiWriteMem(tFile,tMemory,1,tMemory->spLen);
tFile->FsiClose();
tMemory->MemFree();

Die Datei kann zu Debug-Zwecken ausgewertet werden.

Aufbau der XML-Struktur

  • Kopf-Daten

    Im Kopfbereich der XML-Struktur befinden sich allgemeine Informationen zu dem Dokument. In dem Eintrag source befinden sich der Dateiname (Attribut file), die horizontale und vertikale Auflösung (dpix, dpiy) und die Größe der Seite (sizex, sizey). Die Größe einer Seite wird berechnet, indem die Punkte durch die DPI geteilt werden (Größe in Zoll) und das Ergebnis mit 25,4 multipliziert wird (Größe in Millimeter).

    <?xml version="1.0"?>
    <!--XML document generated using OCR technology from Nuance Communications, Inc.-->
    <document xmlns="http://www.scansoft.com/omnipage/xml/ssdoc-schema3.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <summary>
    </summary>
    <page ocr-vers="OmniPageCSDK16" app-vers="ArcFlow">
    <description backColor="ffffff">
    <source file="..." dpix="400" dpiy="400" sizex="3307" sizey="4678"/>
    <theoreticalPage size="Custom" marginLeft="0" marginTop="0" marginRight="0" marginBottom="0" width="3307" height="4678"/>
    </description>
    

    In dem obigen Beispiel ist die Seite 210 mm breit (sizex/dpix*25,4 = 3307/400*25,4 = 209,9945) und 297 mm hoch (sizey/dpiy*25,4 = 4678/400*25,4 = 297,053).

  • Textbereiche

    Die Seite wird hierarchisch in verschiedenen Bereiche aufgeteilt. Auf oberster Ebene sind das Textbereiche (textZone). Diese werden in Zeilen (ln) und dann weiter in Worte (wd) aufgeteilt. Im Wortbereich befindet sich dann das erkannte Wort (run).

    <zones>
    <textZone l="853" t="853" r="4601" b="1364" fillingMethod="omnifont" recognitionModule="omnifontPlus2w" chrFilter="all">
    <ln l="853" t="853" r="4597" b="1361" baseLine="1354" bold="true" underlined="none" fontSize="3400">
    <wd l="853" t="853" r="4597" b="1361"><run backColor="ffffff" language="de">
    Produktinfo</run>
    </wd>
    <space/>
    </ln>
    </textZone>
    ...
    <zones>
    

    In diesem Beispiel befindet sich in dem Textbereich nur eine Zeile mit dem Wort "Produktinfo". Weitere Textbereiche sind aus Gründen der Übersichtlichkeit ausgeblendet.

    Wird eine Tabelle erkannt, befindet sich im Textbereich eine weitere Unterteilung in Spalten (cellZone). Diese wird dann weiter in Zeilen und Wöter aufgeteilt.

    Die Position eines Textbereiches, einer Zeile oder eines Wortes kann über die Attribute l, t, r und b ermittelt werden. Die Angabe erfolgt in Twips (1 Twip = 1/1440 Zoll). Die Werte können mit 25,4/1440 multipliziert werden, um Werte in Millimeter zu erhalten. Die Werte entsprechen dem Abstand vom linken bzw. vom oberen Seitenrand.

    Der Begriff "Produktinfo" befindet sich im Bereich 15-81 mm vom linken Rand und 15-24 mm vom oberen Rand.

  • Abschluss der Datei

    In dem Abschnitt werden die öffnenden Tags aus dem Kopf-Bereich geschlossen.

    </page>
    </document>
    

Verarbeitung von XML-Strukturen

Nachdem der XML-Text in ein Memory-Objekt übertragen wurde, kann er mit der Anweisung (siehe CONZEPT 16 Hilfe) in eine XML-Struktur überführt werden. Soll lediglich das erste Vorkommen eines Begriffes und dessen Position ermittelt werden, kann auch das Memory-Objekt durchsucht und die entsprechende Textstelle ausgewertet werden. Bei komplexeren Aufgaben empfiehlt sich die Verwendung der XML-Struktur.

local
{
  tResult : int;
  tMemory : handle;
  tXmlDoc : handle;
}

{
  tMemory # AfMemAllocate(_MemAutoSize);
  tMemory->spCharset # _CharsetUTF8;
  tResult # AfArcFileXmlTextRead(tMemory,1); // first Page
  if (tResult != _ErrOk)
  {
    // Error handling
    ...
    tMemory->MemFree();
    return;
  }
  tXmlDoc # AfCteOpen(_CteNode, _CteChildList | _CteAttribList | _CteAttribTree);
  tResult # tXmlDoc->XmlLoad('',0,tMemory);
  tMemory->MemFree();
  if (tResult != _ErrOk)
  {
    // Error handling
    ...
    tXmlDoc->AfCteCloseAll();
  }
  ...
}

Beispiel:

Die folgende Funktion gibt das Wort zurück, das an einer bestimmten Stelle auf der Seite steht. Die Position des Wortes wird in einer Konstanten in 10tel Millimeter angegeben. Es werden Funktionen definiert, die bestimmte Attribute aus einem XML-Knoten lesen (getNodeAttrUnits()), aus den Attributen l, t, r und b ein Rechteck bilden (getNodeAttrRectUnits()) und prüfen, ob ein Wort an einem vorgegebenen Punkt steht (xmlFindWdByPoint()).

define
{
  sPointOnPage : PointMake(1900,250) // Position 2.5 cm from top, 19 cm from left 
}

sub getNodeAttrUnits
(
  aXmlNode : handle;
  aName    : alpha;
)
: int

  local
  {
    tXmlNode : handle;
  }
{
  tXmlNode # aXmlNode->CteRead(_CteAttribList | _CteFirst | _CteSearch, 0, aName);
  if (tXmlNode > 0)
    return CnvIA(tXmlNode->spValueAlpha);
  else
    return 0;
}

sub getNodeAttrRectUnits
(
  aXmlNode    : handle;
)
: rect

  local
  {
    tResult : rect;
  }
{
  tResult:left   # aXmlNode->getNodeAttrUnits('l');
  tResult:top    # aXmlNode->getNodeAttrUnits('t');
  tResult:right  # aXmlNode->getNodeAttrUnits('r');
  tResult:bottom # aXmlNode->getNodeAttrUnits('b');
  return tResult;
}

sub xmlFindWdByPoint
(
  aXmlNode    : handle;
  aPoint      : point;
)
: handle

local
{
  tXmlNode : handle;
  tRect    : rect;
  tResult  : handle;
}

{
  for   tXmlNode # aXmlNode->CteRead(_CteChildList | _CteFirst);
  loop  tXmlNode # aXmlNode->CteRead(_CteChildList | _CteNext, tXmlNode);
  while (tXmlNode > 0)
  {
    if (tXmlNode->spName = 'wd')
    {
      tRect # tXmlNode->getNodeAttrRectUnits();

      if (aPoint:x >= tRect:left and aPoint:x <= tRect:right and
          aPoint:y >= tRect:top and aPoint:y <= tRect:bottom)
      {
          return tXmlNode;
      }
      cycle;
    }

    tResult # xmlFindWdByPoint(tXmlNode,aPoint);
    if (tResult > 0)
      return tResult;
  }
  return 0;
}

Für den Aufruf der Funktionen muss der XML-Text gelesen und in eine Knotenstruktur geladen werden. Anschließend wird der angegebene Punkt in seine Position in Twips umgerechnet und der Funktion xmlFindWdByPoint() übergeben. Das gesuchte Wort befindet sich in einem untergeordneten Knoten. Das Wort wird mit der Funktion getWord() ermittelt.

sub getWord
(
  aWdNode    : handle;
  var aValue : alpha;
)
: int;

local
{
  tHdlNode : handle;
}

{
  if (HdlInfo(aWdNode,_HdlExists) = 0)
  {
    aValue # '';
    return(_ErrHdlInvalid);
  }
  tHdlNode # aWdNode->CteRead(_CteChildList | _CteFirst); // run element
  if (tHdlNode <= 0)
  {
    aValue # '';
    return(_ErrGeneric);
  }
  tHdlNode # tHdlNode->CteRead(_CteChildList | _CteFirst); // text element
  if (tHdlNode <= 0)
  {
    aValue # '';
    return(_ErrGeneric);
  }
  aValue # tHdlNode->spValueAlpha;
  return(_ErrOk);
}

main
(
)
: logic

local
{
  tResult     : int;
  tMemory     : handle;
  tXmlDoc     : handle;
  tTarget     : point;
  tNodeTarget : handle;
  tTargetWord : alpha(250);
}

{
  tMemory # AfMemAllocate(_MemAutoSize);
  tMemory->spCharset # _CharsetUTF8;
  tResult # AfArcFileXmlTextRead(tMemory,1); // read XML of first Page
  tXmlDoc # AfCteOpen(_CteNode, _CteChildList | _CteAttribList | _CteAttribTree);
  tResult # tXmlDoc->XmlLoad('',0,tMemory); // convert to xml structure
  tMemory->MemFree();
  
  tTarget # sPointOnPage; // convert position from 1/10 mm to twips
  tTarget:x # tTarget:x * 1440 / 254;
  tTarget:y # tTarget:y * 1440 / 254;
  tNodeTarget # tXmlDoc->xmlFindWdByPoint(tTarget);
  if (tNodeTarget = 0)
  {
    // nothing found at the given point
    ...
  }
  else
  {
    // get the word at that point
    tResult # getWord(tNodeTarget, var tTargetWord);
  }
  ...
  return(true);
}

Neben den allgemeinen Fehlerwerten können folgende Werte zurückgegeben werden:

Konstante Wert Bedeutung
_ErrOk 0 ok - kein Fehler aufgetreten
_ErrHdlInvalid -191 Das übergeben Memory-Objekt existiert nicht.

Für weitere CONZEPT 16-spezifische Rückgabewerte siehe die aktuelle CONZEPT 16-Hilfe.