2008-10-29 31 views
5

Tôi đang cố gắng để đi bộ mặc dù cây của các đối tượng PdfItem trong một tài liệu PDF hiện có bằng cách sử dụng PDFSharp trong C#.Làm cách nào để đi qua cây đối tượng Pdf trong PDFSharp?

Tôi muốn tạo cấu trúc phân cấp của tất cả các đối tượng như tôi làm - giống như ví dụ "PDF Explorer" - nhưng tôi muốn nó là một cây thay vì danh sách phẳng của tất cả các đối tượng.

Nút gốc là document.Internals.Catalog. Và tôi muốn đi qua tất cả tài liệu.Internals.Catalog.Elements cho đến khi tôi đã truy cập mọi phần tử.

Một trong những vấn đề mà tôi gặp phải là có các tham chiếu vòng tròn trong cây và tôi không thể tìm ra cách phát hiện chúng.

Có mẫu mã nào không?

Trả lời

6

bài này bởi marihanzo trên các diễn đàn PDFSharp đã làm việc cho chúng tôi:

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

Vấn đề duy nhất chúng tôi đã được xử lý các lĩnh vực với \ r \ n trong đó. Đây là bản sao của mã trong trường hợp bài đăng trên diễn đàn bị mất.

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 
} 

và mã gọi:

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

Đọc và phân tích toàn bộ bộ sưu tập và xây dựng cây trong bộ nhớ của riêng bạn. Sau đó đi bộ cây đó.

Các vấn đề liên quan