2016-02-05 64 views
1

我在使用iTextSharp(5.x)將html轉換爲pdf時試圖隱藏包含某個類的圖像元素。如何在從html創建pdf時隱藏具有某個類的圖像?

我無法訪問原始Html,因爲它來自另一個源,但是,我可以在C#中執行基本的東西,例如正則表達式和string.replace。

HTML字符串中的一個簡單的例子是這樣的:

<div> 
    <div> 
     <img src="somepath/desktop.jpg" class="img-desktop">Desktop</img> 
     <img src="somepath/mobile.jpg" class="img-mobile">Mobile</img> 
    </div> 
</div> 

然後得到創建該字符串轉換成使用iTextSharp的該XMLWorker的PDF文件。

我需要隱藏第二個圖像,更一般地說,任何帶有「img-mobile」類的圖像元素。

我已經試過:

  • 添加img.img移​​動{顯示:無}到CSS是創建PDF
  • 添加img.img移​​動{寬度時發送: 0; height:0}添加到CSS
  • Add @media print {img.img-mobile:display:none} 0}到CSS
  • 使用正則表達式來查找具有該類的img元素,然後遍歷匹配,更換空的源代碼的來源和替換字符串與新字符串的原始HTML(我的正則表達式是不斂任何比賽,不幸的是)

     var pattern = "<img.*?class=\"img-mobile.*\"\\s?>.*</img>"; 
         var mobileImages = Regex.Matches(innerHtml, pattern); 
         var srcPattern = "src=\".*\" "; 
         foreach (var imageElement in mobileImages) 
         { 
    
          var replaceString = Regex.Replace(imageElement.ToString(), srcPattern, " "); 
          innerHtml.Replace(imageElement.ToString(), replaceString); 
         } 
    

我趕緊跑出來關於如何處理這個問題的想法...唯一的優點是,由於工具在其他地方生成它,所以進來的Html是一致的。所以,當用戶「添加一個圖像到該html」它將始終結構相同,所以正則表達式和替換方法是可以接受的,雖然CSS方法會更受歡迎...

回答

1

即使你Regex專家和您的輸入是可以預見的,解析HTML是很難的。更好更簡單的方法是使用經過測試/驗證的解析器,該解析器幾乎適用於所有編程語言。對於.NET,它是HtmlAgilityPack。如果你知道一點的XPath,這是相當類似CSS選擇器,這是很簡單的設置,並選擇要刪除特定的節點:

string RemoveImage(string htmlToParse) 
{ 
    var hDocument = new HtmlDocument() 
    { 
     OptionWriteEmptyNodes = true, 
     OptionAutoCloseOnEnd = true 
    }; 
    hDocument.LoadHtml(htmlToParse); 
    var root = hDocument.DocumentNode; 
    var imagesDesktop = root.SelectNodes("//img[@class='img-desktop']"); 
    foreach (var image in imagesDesktop) 
    { 
     var imageText = image.NextSibling; 
     imageText.Remove(); 
     image.Remove(); 
    } 
    return root.WriteTo(); 
} 

然後您解析HTML傳遞給iTextSharp的:

var parsedHtml = RemoveImage(HTML); 
using (var xmlSnippet = new StringReader(parsedHtml)) 
{ 
    using (FileStream stream = new FileStream(
     outputFile, 
     FileMode.Create, 
     FileAccess.Write)) 
    { 
     using (var document = new Document()) 
     { 
      PdfWriter writer = PdfWriter.GetInstance(
       document, stream 
      ); 
      document.Open(); 
      XMLWorkerHelper.GetInstance().ParseXHtml(
       writer, document, xmlSnippet 
      ); 
     } 
    } 
} 

適用於您提供的HTML片段。

UPDATE,關於 '批准' 的代碼後評論:

啊哈,可怕的CCB。知道那是怎麼回事。 :(如果HtmlAgilityPack沒有通過,這是一個替代解決方案,雖然它可能不是有史以來最好的Regex。;)

const string HTML = @" 
<div> 
    <p class='img-desktop'>Paragraph</p> 
    <div> 
     <img src='somepath/desktop.jpg' class='img-desktop'>Desktop</img> 
     <img src='somepath/mobile.jpg' class='img-mobile'>Mobile</img> 
    </div> 
    <div> 
     <img src='somepath/desktop.jpg' alt='img-desktop' title='img-desktop' class=""img-desktop"">Desktop 
</IMG> 
     <img src='somepath/mobile.jpg' class='img-mobile'>Mobile</img> 
    </div> 
</div>"; 

public void Go() 
{ 
    var regex = new Regex(
     // initial update 
     // @"<img[^>]*class='?""?'?img-desktop""?[^>]*>.*?</img>", 

     // after seeing accepted answer, noticed a bad copy/paste. 
     // above works, but for readability should have been this: 
     @"<img[^>]*class='?""?img-desktop""?'?[^>]*>.*?</img>", 
     // and also noticed above can be shortened to this, which works too 
     // @"<img[^>]*class=[^>]*img-desktop[^>]*>.*?</img>" 
     RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline 
    ); 
    Console.WriteLine(regex.Replace(HTML, "")); 
} 

Regex給你萬一額外的迴旋餘地,你正在處理的實際HTML是不準確上面貼。

+0

感謝您的回覆!我也開始走這條路,但由於它沒有得到「客戶的批准」,所以不得不轉而離開它,這意味着它必須通過審批委員會。建築師有信心它應該沒問題,但我想探索其他選擇......聽起來好像沒有任何:)我會用更復雜的html給出這個結果並回復給你。 – JasonWilczak

+0

更新爲'Regex'替代。 – kuujinbo

+0

我希望我能夠贊成這50次,謝謝!正則表達式路徑是我目前所擁有的,並且完美運行!當我回來時,我會在星期一去HtmlAgilityPack,但至少我知道B計劃的作品,再次感謝你! – JasonWilczak