簡體   English   中英

HTML 到 PDF 動態添加目錄 (TOC)

[英]HTML to PDF adding a table of contents (TOC) dynamically

我正在使用 iText 7 將 html 轉換為 PDF,但我什至找不到關於如何將目錄添加到最終 PDF 的示例。 在此處遵循 iText 示例時,將文本轉換為 PDF 並添加 TOC 是一項簡單的任務,但顯然將 HTML 轉換為 PDF 時是不可能的。

要求很簡單,只要找到所有的 HTML 標簽屬性“data-toc”並使用該值創建 TOC

這是我到目前為止使用的文本到 PDF 示例中使用的相同方法得到的結果

  • VS 2019

程序.cs

using System.IO;

namespace ConsoleApp
{
    class Program
    {
        private const string SRC = @"C:\iText\sxsw.html";
        private const string DEST = @"C:\iText\sxsw.pdf";

        static void Main(string[] args)
        {
            FileInfo file = new FileInfo(DEST);

            file.Directory.Create();

            new HtmlAndToc().CreatePdf(SRC, DEST);
        }
    }
}

HtmlAndTOC.cs

using iText.Html2pdf;
using iText.Html2pdf.Attach;
using iText.Html2pdf.Attach.Impl;
using iText.Html2pdf.Resolver.Font;
using iText.Kernel.Pdf;
using iText.StyledXmlParser.Node;
using System;
using System.IO;

namespace ConsoleApp
{
    class HtmlAndToc
    {
        public void CreatePdf(string src, string dest)
        {
            ConverterProperties properties = new ConverterProperties();
            properties.SetFontProvider(new DefaultFontProvider(true, true, true));

            // Custom Factory
            properties.SetTagWorkerFactory(new CustomTagWorkerFactory());

            PdfWriter writer = new PdfWriter(dest);
            PdfDocument pdfDoc = new PdfDocument(writer);
            pdfDoc.SetTagged();

            FileStream htmlStream = new FileStream(src, FileMode.Open);

            HtmlConverter.ConvertToPdf(htmlStream, pdfDoc, properties);

            htmlStream.Close();
            pdfDoc.Close();
        }
    }

    public class CustomTagWorkerFactory : DefaultTagWorkerFactory
    {
        public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context)
        {
            string dataTocAttrValue = tag.GetAttribute("data-toc");

            if (String.IsNullOrWhiteSpace(dataTocAttrValue))
            {
                return null;
            }

            // At this point I have the HTML element and the data-toc attribute value that is a TOC title to be associated to a page number
            // Because the data-toc attribute can be on any HTML element type I couldn't find a way to create an Outline/AddDestination nor 
            // a way to SetNextRenderer to keep the page number updated as the Text to PDF example does in
            // https://itextpdf.com/en/resources/examples/itext-7/toc-first-page

            Console.WriteLine(dataTocAttrValue);

            return null;
        }
    }
}

這里有一個示例 HTML 文件:

 <!DOCTYPE html> <html> <head> <!-- example from: https://itextpdf.com/ --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="css/sxsw.css"/> <link rel="stylesheet" media="print only" href="css/sxsw_print.css"> <!-- Based on the reponsive design example found at https://www.w3schools.com/css/css_rwd_intro.asp --> </head> <body> <div class="header"> <h1>SXSW</h1> </div> <div class="container"> <div class="one col-1-m col-1 menu"> <ul data-toc="Activities"> <li>Interactive</li> <li>Film</li> <li>Music</li> <li>Comedy</li> </ul> </div> <div class="two col-3-m col-3 "> <h1>South by Southwest</h1> <p>The South by Southwest&reg; (SXSW&reg;) Conference &amp; Festivals in Austin (TX) celebrate the convergence of the interactive, film, and music industries. Fostering creative and professional growth alike, SXSW&reg; is the premier destination for discovery.</p> </div> <div class="three col-4-m col-1"> <div data-toc="South by Southwest Conference" class="aside"> <h2>Conference</h2> <p>The SXSW conference is an amazing conglomeration of people, places, brands, music, tech and film.</p> <h2>Festivals</h2> <p>The different SXSW festivals take place for 10 days in mid-March Every year, with SXSW Interactive lasting for 5 days, Music for 6 days, and Film &amp; Comedy running concurrently for 9 days.</p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <h2>Exhibitions</h2> <p>Trade Show, Flatstock, SXSW Marketplace, Job Market, SXSW Create, Gaming Expo, Southbites Trailer Park, Spotlights.</p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> </div> </div> </div> <div class="container"> <h2 class="header">SXSW Conference and festivals</h2> <p data-toc="SXSW Conference and festivals"> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <p> Growing from a singular night's celebration of comedy's biggest names into a week-long whirlwind of a festival, the SXSW Comedy Festival presents uniquely diverse programming that highlights exceptional emerging and established talent. </p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <p> Growing from a singular night's celebration of comedy's biggest names into a week-long whirlwind of a festival, the SXSW Comedy Festival presents uniquely diverse programming that highlights exceptional emerging and established talent. </p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <p> Growing from a singular night's celebration of comedy's biggest names into a week-long whirlwind of a festival, the SXSW Comedy Festival presents uniquely diverse programming that highlights exceptional emerging and established talent. </p> <p> The SXSW Conference features 25 different tracks that prove the most unexpected discoveries happen when diverse topics and people come together. In 2017, SXSW equipped 421,900 people from 95 countries. There were 2,887 sessions by 5,280 speakers for 70,969 attendees. In addition to its conference, SXSW is known for its four festivals: interactive, film, music, and comedy. </p> <p> The evening networking events that make up the SXSW Interactive Festival range from parties, award presentations, private events, and more. In 2017, there were 1,084 official parties and events. </p> <p> The SXSW Film Festival has become known for the high caliber and diversity of films presented, and for its smart, enthusiastic audiences. Running the length of SXSWeek, Film festival attendees can connect with tech and music industry experts for an unparalleled experience at the forefront of discovery, creativity, and innovation. SXSW 2017 brought 171 Shorts, 130 Features, of which 83 World Premieres for 70,547 Attendees. </p> <p> The SXSW Music Festival is the most influential music industry event in the world. Record labels, booking agencies, management and PR firms, export offices, publishers, media outlets, tastemakers, and lifestyle brands converge to see thousands of artists perform in venues all throughout downtown Austin. In 2017, there were 167,800 attendees for 2,085 Performing Acts, of which 544 International acts from 63 different countries. </p> <p> Growing from a singular night's celebration of comedy's biggest names into a week-long whirlwind of a festival, the SXSW Comedy Festival presents uniquely diverse programming that highlights exceptional emerging and established talent. </p> <h2 class="header">Exhibitions</h2> <div class="container"> <div class="col-2-m col-3"> <div><span data-toc="Exhibitions One" class=exhibition>SXSW Trade Show:</span> The all-encompassing exhibition for creative industries.</div> <div><span data-toc="Exhibitions Two" class=exhibition>Flatstock:</span> The world's top gig posters and artists.</div> <div><span data-toc="Exhibitions Three" class=exhibition>SXSW Marketplace:</span> One big pop-up shop at the center of SXSW.</div> <div><span class=exhibition>Job Market:</span> Where innovative talent and companies connect.</div> </div> <div class="col-2-m col-3"> <div><span data-toc="Exhibitions Four" class=exhibition>SXSW Create:</span> Hands on creative fun for imaginations of all ages.</div> <div><span data-toc="Exhibitions Six"class=exhibition>Gaming Expo:</span> The hub of gaming culture at SXSW.</div> <div><span class=exhibition>Southbites Trailer Park:</span> Featuring some of the best food trucks around.</div> <div><span class=exhibition>Spotlights:</span> Highlighting one-one-one connections with promising startups.</div> </div> </div> </div> </body> </html>

我希望這是一個好問題,並提前感謝您的幫助

我的答案與 Alexey 的答案基本相同,只是我會嘗試簡化一下。

其中大部分將使用目標計數器的文檔,該文檔位於此處: https : //www.oxygenxml.com/doc/versions/23.1/ug-editor/topics/dg-target-counter-function.html

遵循這個基本結構。 在您的文檔正文中,為您想要鏈接的任何內容添加一個 id。 在您的目錄中,為每個 id 添加一個 href:

<html>
  <body>

    <div class="toc-container">
      <div class="toc-row"><a href="#one">Link To Page One</a></div>
      <div class="toc-row"><a href="#two">Link To Page Two</a></div>
    </div>

    <div class="content-container">
      <div class="page" id="one">Page One Content Here</div>
      <div class="page" id="two">Page Two Content Here</div>
    </div>

  </body>
</html>

實現目錄的 css 非常簡單:

.toc-row a::after {
  content: leader('.') target-counter(attr(href), page, decimal);
}

就是這樣。 目標計數器使用 href 獲取頁碼並將該頁碼放入您的目錄中。 您可以隨意設置樣式,但基本樣式最終看起來像這樣:

目錄示例

我的答案是在 Java 中,但您可以輕松地將其轉換為 .NET,因為我將使用的Jsoup版本已嵌入到 iText 中,其余的轉換基本上是將方法名稱更改為從大寫字母開始。

現在可以使用純pdfHTML 3.0.3+生成目錄,但這自然需要對 HTML 文件進行一些預處理。

這個想法是我們將循環使用data-toc標記的元素並創建相應的目錄元素。 最有趣的部分是生成頁碼,指示我們引用的內容所在的頁面。 為此,我們將使用target-counter CSS 函數,並且我們還將使用具有唯一 ID 的data-toc屬性標記所有元素,以便能夠在target-counter的上下文中引用它們,也可以跳轉到純鏈接中的那些元素。

這是一個帶有一些幫助注釋的示例代碼:

Document htmlDoc = Jsoup.parse(new File("path/to/in.html"), "UTF-8");

// This is our Table of Contents aggregating element
Element tocElement = htmlDoc.body().prependElement("div");
tocElement.append("<b>Table of contents</b>");

// We are going to build a complex CSS
StringBuilder tocStyles = new StringBuilder().append("<style>");

Elements tocElements = htmlDoc.select("[data-toc]");
for (Element elem : tocElements) {
    // Here we create an anchor to be able to refer to this element when generating page numbers and links
    String id = UUID.randomUUID().toString();
    elem.attr("id", id);

    // CSS selector to show page numebr for a TOC entry
    tocStyles.append("*[data-toc-id=\"" + id + "\"] .toc-page-ref::after { content: target-counter(#" + id + ", page) }");

    // Generating TOC entry as a small table to align page numbers on the right
    Element tocEntry = tocElement.appendElement("table");
    tocEntry.attr("style", "width: 100%");
    Element tocEntryRow = tocEntry.appendElement("tr");
    tocEntryRow.attr("data-toc-id", id);
    Element tocEntryTitle = tocEntryRow.appendElement("td");
    tocEntryTitle.appendText(elem.attr("data-toc"));
    Element tocEntryPageRef = tocEntryRow.appendElement("td");
    tocEntryPageRef.attr("style", "text-align: right");
    // <span> is a placeholder element where target page number will be inserted
    // It is wrapped by an <a> tag to create links pointing to the element in our document
    tocEntryPageRef.append("<a href=\"#" + id + "\"><span class=\"toc-page-ref\"></span></a>");
}


tocStyles.append("</style>");

htmlDoc.head().append(tocStyles.toString());

String html = htmlDoc.outerHtml();

HtmlConverter.convertToPdf(html, new FileOutputStream("path/to/out.pdf"));

我使用上面的代碼和您的示例文件得到的結果的可視化表示:

結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM