2008-10-29 11 views
5

J'essaie de parcourir l'arborescence d'objets PdfItem dans un document PDF existant en utilisant PDFSharp dans C#.Comment parcourir l'arborescence des objets PDF dans PDFSharp?

Je veux créer une hiérarchie de tous les objets au fur et à mesure - comme dans l'exemple «PDF Explorer» - mais je veux que ce soit un arbre au lieu d'une liste plate de tous les objets.

Le noeud racine est document.Internals.Catalog. Et je veux parcourir tous les documents.Internals.Catalog.Elements jusqu'à ce que j'ai visité chaque élément. L'un des problèmes que je rencontre est qu'il y a des références circulaires dans l'arbre et je n'arrive pas à comprendre comment les détecter.

Des échantillons de code sont disponibles?

Répondre

6

Ce message par marihanzo sur les forums de PdfSharp a travaillé pour nous:

http://forum.pdfsharp.net/viewtopic.php?f=2&t=527&p=1603

Le seul problème que nous avons eu était la manipulation des champs avec \ r \ n en eux. Voici une copie du code au cas où le post du forum serait perdu.

PDFParser.cs

public class PDFParser 
{ 
    /// BT = Beginning of a text object operator 
    /// ET = End of a text object operator 
    /// Td move to the start of next line 
    /// 5 Ts = superscript 
    /// -5 Ts = subscript 

    #region Fields 

    #region _numberOfCharsToKeep 
    /// <summary> 
    /// The number of characters to keep, when extracting text. 
    /// </summary> 
    private static int _numberOfCharsToKeep = 15; 
    #endregion 

    #endregion 



    #region ExtractTextFromPDFBytes 
    /// <summary> 
    /// This method processes an uncompressed Adobe (text) object 
    /// and extracts text. 
    /// </summary> 
    /// <param name="input">uncompressed</param> 
    /// <returns></returns> 
    public string ExtractTextFromPDFBytes(byte[] input) 
    { 
     if (input == null || input.Length == 0) return ""; 

     try 
     { 
      string resultString = ""; 

      // Flag showing if we are we currently inside a text object 
      bool inTextObject = false; 

      // Flag showing if the next character is literal 
      // e.g. '\\' to get a '\' character or '\(' to get '(' 
      bool nextLiteral = false; 

      //() Bracket nesting level. Text appears inside() 
      int bracketDepth = 0; 

      // Keep previous chars to get extract numbers etc.: 
      char[] previousCharacters = new char[_numberOfCharsToKeep]; 
      for (int j = 0; j < _numberOfCharsToKeep; j++) previousCharacters[j] = ' '; 


      for (int i = 0; i < input.Length; i++) 
      { 
       char c = (char)input[i]; 

       if (inTextObject) 
       { 
        // Position the text 
        if (bracketDepth == 0) 
        { 
         if (CheckToken(new string[] { "TD", "Td" }, previousCharacters)) 
         { 
          resultString += "\n\r"; 
         } 
         else 
         { 
          if (CheckToken(new string[] { "'", "T*", "\"" }, previousCharacters)) 
          { 
           resultString += "\n"; 
          } 
          else 
          { 
           if (CheckToken(new string[] { "Tj" }, previousCharacters)) 
           { 
            resultString += " "; 
           } 
          } 
         } 
        } 

        // End of a text object, also go to a new line. 
        if (bracketDepth == 0 && 
         CheckToken(new string[] { "ET" }, previousCharacters)) 
        { 

         inTextObject = false; 
         resultString += " "; 
        } 
        else 
        { 
         // Start outputting text 
         if ((c == '(') && (bracketDepth == 0) && (!nextLiteral)) 
         { 
          bracketDepth = 1; 
         } 
         else 
         { 
          // Stop outputting text 
          if ((c == ')') && (bracketDepth == 1) && (!nextLiteral)) 
          { 
           bracketDepth = 0; 
          } 
          else 
          { 
           // Just a normal text character: 
           if (bracketDepth == 1) 
           { 
            // Only print out next character no matter what. 
            // Do not interpret. 
            if (c == '\\' && !nextLiteral) 
            { 
             nextLiteral = true; 
            } 
            else 
            { 
             if (((c >= ' ') && (c <= '~')) || 
              ((c >= 128) && (c < 255))) 
             { 
              resultString += c.ToString(); 
             } 

             nextLiteral = false; 
            } 
           } 
          } 
         } 
        } 
       } 

       // Store the recent characters for 
       // when we have to go back for a checking 
       for (int j = 0; j < _numberOfCharsToKeep - 1; j++) 
       { 
        previousCharacters[j] = previousCharacters[j + 1]; 
       } 
       previousCharacters[_numberOfCharsToKeep - 1] = c; 

       // Start of a text object 
       if (!inTextObject && CheckToken(new string[] { "BT" }, previousCharacters)) 
       { 
        inTextObject = true; 
       } 
      } 
      return resultString; 
     } 
     catch 
     { 
      return ""; 
     } 
    } 
    #endregion 

    #region CheckToken 
    /// <summary> 
    /// Check if a certain 2 character token just came along (e.g. BT) 
    /// </summary> 
    /// <param name="search">the searched token</param> 
    /// <param name="recent">the recent character array</param> 
    /// <returns></returns> 
    private bool CheckToken(string[] tokens, char[] recent) 
    { 
     foreach (string token in tokens) 
     { 
      if (token.Length > 1) 
      { 
       if ((recent[_numberOfCharsToKeep - 3] == token[0]) && 
        (recent[_numberOfCharsToKeep - 2] == token[1]) && 
        ((recent[_numberOfCharsToKeep - 1] == ' ') || 
        (recent[_numberOfCharsToKeep - 1] == 0x0d) || 
        (recent[_numberOfCharsToKeep - 1] == 0x0a)) && 
        ((recent[_numberOfCharsToKeep - 4] == ' ') || 
        (recent[_numberOfCharsToKeep - 4] == 0x0d) || 
        (recent[_numberOfCharsToKeep - 4] == 0x0a)) 
        ) 
       { 
        return true; 
       } 
      } 
      else 
      { 
       return false; 
      } 

     } 
     return false; 
    } 
    #endregion 
} 

et le code d'appel:

public override String ExtractText() 
    { 
     String outputText = ""; 
     try 
     { 
      PdfDocument inputDocument = PdfReader.Open(this._sDirectory + this._sFileName, PdfDocumentOpenMode.ReadOnly); 

      foreach (PdfPage page in inputDocument.Pages) 
      { 
       for (int index = 0; index < page.Contents.Elements.Count; index++) 
       { 

        PdfDictionary.PdfStream stream = page.Contents.Elements.GetDictionary(index).Stream; 
        outputText += new PDFParser().ExtractTextFromPDFBytes(stream.Value); 
       } 
      } 

     } 
     catch (Exception e) 
     { 
      PDF_ParseException oEx = new PDF_ParseException(this, e); 
      oEx.Log(); 
      oEx.ToPdf(this._sDirectoryException); 
     } 
     return outputText; 
    } 
0

Lisez et analysez l'intégralité de la collection et créez votre propre arbre en mémoire. Puis marche cet arbre.