Converting HTML with ordered list and div with itextpdf - html-lists

I tried to convert a HTML page with ordered list and some div tags with itextpdf, but it does not seem to work. I created the following simple ordered list structure in HTML to demonstrate the problem:
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<!-- <div> -->
<ol>
<li>A
<ol>
<li>AA</li>
<li>AB</li>
<li>AC
<ul>
<li>ACA</li>
<li>ACB</li>
</ul>
</li>
<li>AD
<ul>
<li>ADA</li>
<li>ADB</li>
</ul>
</li>
</ol>
</li>
</ol>
<!-- </div> -->
</body>
</html>
It works fine so far, and I get the correct, well formatted PDF. When, however, I remove the comment around the div tag, it does not work any more. I get all element of the ordered list in a single line, in the result PDF file like this:
A AAABAC ACAACBAD ADAADB
My method for the conversion looks like this:
private void convertHtmlToPdf(String htmlFilePath, String generatedPdfFilePath) throws IOException, FileNotFoundException, DocumentException {
String fileContent = FileUtils.readFileToString(new File(htmlFilePath));
OutputStream file = new FileOutputStream(new File(generatedPdfFilePath));
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
InputStream is = new ByteArrayInputStream(fileContent.getBytes());
XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
document.close();
file.close();
}
So it is the simplest conversion code. I don't use any CSS, or insert any pictures. In my real code however, I do need to use CSS for the conversion, and the formatting is defined via div elements. So I can not simple remove all the div-s to get the conversion working.
Is it a bug, in itextpdf, or I miss something? Has anybody any idea for a workaround, to deal with this problem?
I am using the actually latest (5.5.6) version of itextpdf.

<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<div>
<ol>
<li>A
<ol>
<li>AA</li>
<li>AB</li>
<li>AC
<ul>
<li>ACA</li>
<li>ACB</li>
</ul>
</li>
<li>AD
<ul>
<li>ADA</li>
<li>ADB</li>
</ul>
</li>
</ol>
</li>
</ol>
</div>
</body>
</html>
this code should be work try it

Related

Flexbox Usage Partially(?) Works In iTextPDF

I am using ITextPDF to create a report. And since the report is going to be a very complex one, I want to use an HTML template which I am creating to create the pdf. But when it comes to flex-box, it only partially works.
What I mean with partially is, when I use below code;
private string HTML = $#"
<!DOCTYPE html>
<html lang=""tr"">
<head>
<meta charset = ""UTF-8"">
<meta http-equiv=""X-UA-Compatible"" content=""IE=edge"">
<meta name = ""viewport"" content=""width=device-width, initial-scale=1.0"">
<title>Print</title>
<link rel=""stylesheet"" href=""https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/css/bootstrap.min.css"">
</head>
<body>
<div class=""d-flex align-items-center justify-content-center bg-primary"">
<div>abcçde</div>
<div>ABCÇDEF</div>
</div>
</body>
</html>
";
public void GeneratePDF()
{
using(var memoryStream = new MemoryStream())
{
using (var pdfWriter = new PdfWriter(Guid.NewGuid().ToString()+".pdf"))
{
pdfWriter.SetCloseStream(false);
HtmlConverter.ConvertToPdf(this.HTML, pdfWriter);
var pdfStream = pdfWriter.GetOutputStream();
pdfStream.Position = 0;
pdfStream.CopyTo(memoryStream);
var result = memoryStream.ToArray();
pdfStream.Dispose();
}
}
}
The justify-content-center works on-point as can be seen below;
But when I change it to justify-content-between it doesn't work;
I also tried to give each div float values, without adding bootstrap.min.css and it doesn't work that way either.
Why would it work with justify-content-center and not justify-content-between?
As mentioned in one of the question's comments, as for now iText provides only initial flex support. Specifying justify-content-between class actualy means setting justify-content:space-between, and thie value is not supported: you could see it from the log message which is thrown while processing such an html:
com.itextpdf.html2pdf.css.apply.util.FlexApplierUtil WARN Flex related property justify-content: space-between is not supported yet.
As a workaround, one indeed could use floats. For example, divs of the following html are processed as expected:
<!DOCTYPE html>
<html lang="tr">
<body>
<div>
<div style="float: left;">abcçde</div>
<div style="float: right">ABCÇDEF</div>
</div>
</body>
</html>
Also flex-direction:column doesn't work

Thymeleaf switch statement including every case

I'm working on my first Spring MVC project and I got stuck at a problem. I have 3 types of users in my application: admin, employee and customer. Depending on the type of user, I would like to have a specific type of menu for each of them. I tried using a switch statement in my thymeleaf template but every case gets included in the output and I don't understand why.
This is the code for my method in the controller:
#RequestMapping(value = "list/{roleId}", method = RequestMethod.GET)
public String listFood(Model model, #PathVariable int roleId){
model.addAttribute("title", "Available Foods");
model.addAttribute("roleId", roleId);
model.addAttribute("foods", foodDao.findAll());
return "food/list";
}
And this is the code from the Thymeleaf template (each fragment will be included in the resulting page):
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments :: head"></head>
<body class="container">
<h1 th:text="${title}">Food</h1>
<div th:switch="${roleId}">
<p th:case="0"><nav th:replace="admin-fragments :: navigation"></nav></p>
<p th:case="1"><nav th:replace="employee-fragments :: navigation"></nav></p>
<p th:case="2"><nav th:replace="customer-fragments :: navigation"></nav></p>
</div>
</body>
</html>
However, if I change the template to the following one then only the correct case will be included in the resulting page.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments :: head"></head>
<body class="container">
<h1 th:text="${title}">Food</h1>
<div th:switch="${roleId}">
<p th:case="0">User is an administrator</p>
<p th:case="1">User is an employee</p>
<p th:case="2">User is a customer</p>
</div>
</body>
</html>
Why isn't the switch from the first template behaving like the one in the second template? What should I change in the first template to be able to have a personalised menu for each type of user? Thank you!

Thymleaf - how to call model Attribute on html document

Im trying to render a webapge and use the thymleaf attribute "url" added with model.addAttribute but the Attribute is not beeing displayed on the html document.
My document.html file path is here:
/templates/webpage/document.html
#RequestMapping(value = "/webpage/document")
public String document(HttpServletRequest req, Model model) {
model.addAttribute("dialogurl", url);
return "/webpage/document";
}
Here is the html document
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:include="wrapperdialog :: page">
<head>
<title></title>
</head>
<body>
<div th:fragment="content">
<div class="container dialogpage">
<div class="row">
<div class="col-md-12">
<div id="typeform" th:attr="data-url=*{dialogurl}">
</div>
</div>
</div>
</div>
</div>
Please use this expression to bind dialog url: #{${dialogurl}}
<div id="typeform" th:attr="data-url=#{${dialogurl}}">
# prefix is used to specify a link and $ prefix is used to bind your model value.
Use $ to bind data.
<div id="typeform" th:attr="data-url=${dialogurl}">

Link to a section of an html doc that's been loaded in a div

My site has a "nav" div, with links to different html files, a "sidebar" div with static information, and a "content" div, which the different html files get loaded into. I've also set my url base in the header. One of these html files is a long document, and I'd like to be able to include links to sections of this file. So I named the section headers and used the hashtag to link to them:
portfolio.html snippet:
<BODY>
<a id="top"></a>
<header>
PULSE OXIMETRY IN ZAMBIA<BR>
DENGUE DIAGNOSIS IN NICARAGUA<BR>
EYE HEALTH IN INDIA<BR>
MAS.531 COMPUTATIONAL CAMERA AND PHOTOGRAPHY<BR>
MAS.S60 HANDS ON FOUNDATIONS<BR>
<hr>
</header>
<header><a id="pulseox">PULSE OXIMETRY IN ZAMBIA</a></header>
<img src="pulseOx.PNG" width="500px"><BR>
lorem ipsum
</BODY>
And this works wonderfully when I've opened the html by itself. But when it's been loaded into the "content" div within the meta html file, it tries to take me to <myurlbase>#pulseox. How do I make the <a href="#pulseox"> link refer to html doc within the "content" div? I haven't set a base url in the portfolio.html file.
Here's my meta html doc, if that helps:
<HTML>
<HEAD>
<link rel="stylesheet" type="text/css" href="index_test.css" />
<base href="http://myurl/" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#content").load("home.html");
$(".nav-1").click(function(){
$("#content").load("home.html");
});
$(".nav-2").click(function(){
$("#content").load("about.html");
});
$(".nav-3").click(function(){
$("#content").load("portfolio.html");
});
$(".nav-4").click(function(){
$("#content").load("cv.html");
});
});
</script>
</HEAD>
<BODY>
<div id="nav">
<ul>
<li><a class="nav-1">HOME.</a></li>
<li><a class="nav-2">ABOUT.</a></li>
<li><a class="nav-3">PORTFOLIO.</a></li>
<li><a class="nav-4">CV.</a></li>
</ul>
</div>
<div id="sidebar">
myname
<BR><BR>
</div>
<div id="content"></div>
</BODY>
</HTML>

Visual Studio HTML5 Validation: Element 'img' cannot be nested within element 'a'

I've run into this curious validation error in Visual Studio 2010 with HTML5 validation selected:
Is this a validation error (legitimate or a bug in Visual Studio) or am I missing something obvious and simple?
Edit: added relevant code.
View cshtml:
#model My.Web.ViewModels.ListVideos
#{
ViewBag.Title = "All Videos";
}
#foreach (var item in Model.Videos) {
<a href="#Url.Action("Play", "Player", new { videoId = item.VideoId })">
<img src="http://i2.ytimg.com/vi/#item.PublisherVideoId/default.jpg" alt="#item.Title" style="border: 0" />
</a>
}
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.6.4.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
</head>
<body>
<div class="page">
<header>
<div id="title">
<h1>My Web</h1>
</div>
<div id="logindisplay">
#Html.Partial("_LogOnPartial")
</div>
<nav>
<ul id="menu">
<li>#Html.ActionLink("Videos", "ListVideos", "Player")</li>
<li>#Html.ActionLink("Dev", "Index", "Dev")</li>
</ul>
</nav>
</header>
<section id="main">
#RenderBody()
</section>
<footer>
</footer>
</div>
</body>
</html>
You need visual studio 2010 SP1 web standards update to have this work properly. It is a bug.
See more here: http://blogs.msdn.com/b/webdevtools/archive/2011/06/15/web-standards-update-for-visual-studio-2010-sp1.aspx?PageIndex=2
Get the web standards update here:
http://visualstudiogallery.msdn.microsoft.com/a15c3ce9-f58f-42b7-8668-53f6cdc2cd83
If you check the W3C documentation about Html5 you will find that you can have inside a a tag anything if it's not button or other links.
The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links).

Resources