2017-04-19 9 views
0

현재 데이터베이스의 여러 행에있는 데이터를 기반으로 PDF를 만드는 작업 버전이 있습니다. 데이터베이스의 각 행에 대해 PDF에 새 페이지를 작성합니다. 이것은 모두 잘 작동합니다. 이제 HTML이 제대로 렌더링되도록 각 행의 일부 필드를 구문 분석해야합니다. 나는 전체 문자열을 가져 와서 문서를 파싱하고 있지만 전체 문서를 파싱하는 것을 보여주는 see an example here을 사용할 수 있습니다.다른 페이지의 루프에서 iText를 사용하여 HTML 덩어리를 파싱하십시오.

필요한 것은 구문 분석 할 HTML의 특정 필드 만 사용하여 개별 서식이 지정된 페이지를 만드는 것입니다. 이것을 할 수 있습니까?

PdfFont fTimes = PdfFontFactory.CreateFont(FontConstants.TIMES_ROMAN); 
PdfFont fTimesBold = PdfFontFactory.CreateFont(FontConstants.TIMES_BOLD);      

// create the first page here 
doc.Add(new Paragraph("Abstract Submissions for " + eventName).SetFont(fTimes).SetFontSize(18).SetFontColor(Color.BLACK)); 
doc.Add(new Paragraph("Section Name: " + GetSectionName(ddlSections.SelectedValue)).SetFont(fTimes).SetFontSize(14).SetFontColor(Color.BLACK)); 
doc.Add(new Paragraph("Created: " + DateTime.Now.ToString("dddd, MMMM d, yyyy h:mm tt")).SetFont(fTimes).SetFontSize(11).SetFontColor(Color.BLACK)); 

// iterate through each of the items 
foreach (DataRow row in dsItems.Tables[0].Rows) 
{ 
    // create a new page for each abstract submission 
    doc.Add(new AreaBreak(iText.Layout.Properties.AreaBreakType.NEXT_PAGE)); 
    doc.Add(new Paragraph(ValidationHelper.GetString(row["PresentationType"], "")).SetFont(fTimes).SetFontSize(12).SetFontColor(Color.BLACK)); 
    doc.Add(new Paragraph(ValidationHelper.GetString(row["PresentationTitle"], "")).SetFont(fTimes).SetFontSize(16).SetFontColor(Color.BLACK)); 
    // html field 
    doc.Add(new Paragraph(ValidationHelper.GetString(row["Authors"], "")).SetFont(fTimes).SetFontSize(12).SetFontColor(Color.BLACK)); 
    // html field 
    doc.Add(new Paragraph(ValidationHelper.GetString(row["Abstract"], "")).SetFont(fTimes).SetFontSize(12).SetFontColor(Color.BLACK)); 
} 

doc.Close(); 

내가 그렇게 클라이언트가 즉시 파일 시스템에 저장하지 않아도 다운로드 할 수있는 MemoryStreamFileStream을 사용하고주의해야한다 : 아래

는 새로운 페이지를 생성 내가 가진 몇 가지 예제 코드 .

** 편집 - 당신이 iText를 번역기에 자신의 XML/HTML을 만들 수있는이 같은 패턴으로 추가 샘플 데이터 **

<table> 
    <tr> 
     <td>Poster</td> 
     <td>Abstract 1</td> 
     <td><strong><em>Doctor Name 1</em></strong> <strong>Doctor Name 2</strong></td> 
     <td><p>Some really long text <strong>which can have</strong> some different basic HTML <u>formatting in it</u></p></td> 
    </tr> 
    <tr> 
     <td>Presentation</td> 
     <td>Abstract 2</td> 
     <td><strong>Doctor Name 15 </strong><em>Doctor 3</em></td> 
     <td><p>Some really long text which can have some different basic HTML <em>formatting in it</em></p></td> 
    </tr> 
</table> 
+0

파싱/렌더링 할 콘텐츠 샘플을 공유 할 수 있습니까? 이 내용은 서식있는 텍스트 편집기에서와 같이 일관된 서식을 가진 html의 일부 사소한 하위 집합입니까 아니면 야생 html/css 항목입니까? – COeDev

+0

불쌍한 형식의 샘플 데이터를 @COeDev 추가했습니다. 기본적으로 태그의 모든 것이 데이터베이스 열입니다. 내가 편집자없이 마크 업의 모든 효과를 얻을 수 있었던 유일한 방법. –

+0

"strong", "p", "em"및 html이 유효한 xml이 아닌 경우이 항목을 쉽게 파싱하고 itext 요소를 만들 수 있습니다. – COeDev

답변

0

. 필요한 태그를 구현하기 만하면됩니다.

internal interface ICustomElement { IEnumerable<IElement> GetContent(); } 

internal class CustomElementFactory { 
    public ICustomElement GetElement(XmlNode node) { 
    switch (node.Name) { 
     case "p": return new CustomParagraph (node, this); 
     // implement the tags you need using the ICustomElement interface 
     default: // e.g. treat unknown nodes as text 
    } 
} 

public class PdfCreator { 
    public byte[] GetPdf(XmlDocument template) { 
    PdfDocument doc ... 
    CustomElementFactory factory ... 
    foreach(XmlNode node in template.ChildNodes) { 
     doc.AddElements(factory.GetElement(node).GetContent()); 
     // the point why all this is possible in such an easy generic way is that almost every itext element implements the IElement interface and therefore can be added to the document this way. And containers like PdfPCell are taking IElements as well. 
     // Good job itext guys! ;) 
    } 

    return doc.CloseDocument(); 
    } 
} 

// here comes the magic: 

internal class CustomParagraph : ICustomElement { 
    // ctor storing the xmlnode and factory in private field 
    public IEnumerable<IElement> GetContent() { 
    Paragraph p = new Paragraph(); 
    p.Add(node.InnerText); // create a underline or bold or whatever font here when you are implementing the special html tags 

    // if the node has child elements, get their content by calling the factory.GetElement(child).GetContent() for each child. Then loop over the the IElement.Chunks collection of each IElement to add the containing chunks to the paragraph of this scope. This way you will be able to process nested html tags recursively. 
    // find a way to pass the style information of this scope to the factory when processing child nodes, so you will be able to render <strong>bold<u>underlindANDBOLD</u></strong> stuff correctly 

    return new List<IElement> { p }; 
    } 
} 

일부 작업과 미세 조정이 필요하지만 수행 할 수 있습니다.