I am trying to generate class by which I can generate a HTML code from an XML file. It does generate the HTML code but when I have more than one tag in my XML file its value is reset.
I hope you could help me.
Here is my code in C#:
public class GenerateHTMLClass
{
public string htmlstringbegin = "<HTML><HEADER><title>My Web-page</title></HEADER><BODY><form>\r\n";
public string htmlstringend = "</form></BODY></HTML>";
public string htmlstring = "";
public GenerateHTMLClass(string xmlfileaddress, string htmlfilenaddress)
{
string id = "";
string name = "";
string type = "";
string value = "";
string htmlstring = "";
XmlTextReader reader = new XmlTextReader(xmlfileaddress);
while (reader.Read())
{
switch (reader.Name)
{
case "GUID":
id = reader.ReadString();
break;
case "Title":
name = reader.ReadString();
break;
case "Type":
type = reader.ReadString();
break;
}
}
htmlstring += "<" + type + " id=" + id + " value=" + name + "/>" + name + "</" + type + ">";
using (FileStream fs = new FileStream(htmlfilenaddress, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(fs, Encoding.UTF8))
{
writer.Write(htmlstringbegin + htmlstring + htmlstringend);
}
}
}
}
My xml file:
<Groups>
<Group1>
<Item1>
<Type>Button</Type>
<GUID>124342345</GUID>
<Title>Name</Title>
</Item1>
</Group1>
<Group2>
<Item2>
<Type>textarea</Type>
<GUID>1243dsfs42345</GUID>
<Title>Name</Title>
</Item2>
</Group2>
</Groups>
Try this:
public void GenerateHTMLClass(string xmlfileaddress, string htmlfilenaddress)
{
List<string> id = new List<string>();
List<string> name = new List<string>();
List<string> type = new List<string>();
List<string> value = new List<string>();
string htmlstring = "";
XmlTextReader reader = new XmlTextReader(xmlfileaddress);
while (reader.Read())
{
switch (reader.Name)
{
case "GUID":
id.Add(reader.ReadString());
break;
case "Title":
name.Add(reader.ReadString());
break;
case "Type":
type.Add(reader.ReadString());
break;
}
}
int i=0;
foreach (var item in id)
{
htmlstring += "<" + type[i] + " id=" + item + " value=" + name[i] + "/>" + name[i] + "</" + type[i] + ">";
i++;
}
using (FileStream fs = new FileStream(htmlfilenaddress, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(fs, Encoding.UTF8))
{
writer.Write(htmlstringbegin + htmlstring + htmlstringend);
}
}
}
But better use XElement class
Try putting the HTML addition code
htmlstring += "<" + type + " id=" + id + " value=" + name + "/>" + name + "</" + type + ">";
into the while loop. This way it will append for every tag, rather than just once after reading all tags.
EDIT: It's slightly more complex, sorry. Change your XML like so:
<Groups>
<Group>
<Item>
<Type>Button</Type>
<GUID>124342345</GUID>
<Title>Name</Title>
</Item>
</Group>
<Group>
<Item>
<Type>textarea</Type>
<GUID>1243dsfs42345</GUID>
<Title>Name</Title>
</Item>
</Group>
</Groups>
Then load it, create a new line for each Item tag. I've used the XElement parser rather than XmlTextReader for ease of use.
var reader = XElement.Load(xmlfileaddress);
foreach (var item in reader.Descendants("Item"))
{
var id = item.Element("GUID").Value;
var name = item.Element("Title").Value;
var type = item.Element("Type").Value;
htmlstring += "<" + type + " id=" + id + " value=" + name + "/>" + name + "</" + type + ">";
}
This will get all your <Item> tags, read their 3 properties, and create a new line for them. If you plan on creating large documents this way, it's advisable to replace your string htmlstring; with a StringBuilder, for performance.
Related
OK, so I received an answer that I am not asking the question correctly. It is not writing each line to the text files. It is not writing anything at all. It build successfully when run, but nothing is written out with StreamWriter. I am not sure what I I am doing wrong with my questions. If this is not the correct way to ask the question, can someone tell me how to ask the question?
class Program
{
static void Main(string[] args)
{
var input = #"C:/Users/cswenson/Desktop/TestProgram/test.txt";
var outputp = #"C:/Users/cswenson/Desktop/TestProgram/preout.txt";
var outputm1 = #"C:/Users/cswenson/Desktop/TestProgram/match1.txt";
var outputm2 = #"C:/Users/cswenson/Desktop/TestProgram/match2.txt";
using (var sr = new StringReader(input))
using (var psw = new StreamWriter(outputp, true))
using (var o1sw = new StreamWriter(outputm1, true))
using (var o2sw = new StreamWriter(outputm2, true))
{
foreach (string line in File.ReadLines(input))
{
string preout = line.Substring(1, 8) + " " + line.Substring(374, 329) + " " + line.Substring(4937, 639);
psw.WriteLine(preout);
string match1 = line.Substring(1, 8) + " " + line.Substring(9, 365) + " " + line.Substring(703, 1786);
o1sw.WriteLine(match1);
string match2 = line.Substring(1, 8) + " " + line.Substring(2489, 2448);
o2sw.WriteLine(match2);
}
}
}
}
I need to read Parklist item in my Json stream. When I try this with string variable, it work :
string jsonString = "[{\"Project\":\"example\", \"Ref\":\"001BC50C70000A21\", \"Latitude\":43.643166, \"Longitude\":1.454769, \"ParkList\": [{\"Id\":\"001BC50C70000A21P1\", \"State\":1, \"DateTime\":\"2018-02-15T08:07:18.987Z\"}, {\"Id\":\"001BC50C70000A21P2\",\"State\":1,\"DateTime\":\"2018-02-15T08:11:41.824Z\"}]}]";
List<KMessage> kMsg = JsonConvert.DeserializeObject<List<KMessage>>(jsonString);
foreach (Parklist item in kMsg[0].Parklist)
{
Console.WriteLine("Id: " + item.ParkId + " State: " + item.ParkState + " DateTime: " + item.ParkDateTime);
}
But when I try to convert stream in string for doing same things, Parklist is empty in the new string (each other variable is ok in text var) :
// convert stream to string
StreamReader reader = new StreamReader(KStream);
string text = reader.ReadToEnd();
List<KMessage> kMsg = JsonConvert.DeserializeObject<List<KMessage>>(text);
foreach (Parklist item in kMsg[0].Parklist)
{
Console.WriteLine("Id: " + item.ParkId + " State: " + item.ParkState + " DateTime: " + item.ParkDateTime);
}
Thanks for your help.
I've been writing below code to find and replace the wrong values with right one.
I've two files here, Source=Delimited text file like below.
J48309A0580113A27E053A2DEF40AC8B8,Z9e578475,
7e241974c714459997e20fe6e195ffb1,BD17946 and BD38168,
and my destination xmlJRN file looks like below. (multiple xmlJRN files)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE eGAD SYSTEM "eGAD.Dtd">
<eGAD pakUID="PID_77F0F469AFE61B4A8121AA84EB349B6C">
<document docID="1" docMasterID="1A5D331DDF8A84385F77B621C3F9CD86" docInstanceID="49E3D61E9CE1DF43BDD042F296913C88">
<VendorId>7618CEADE31441C99FE1BC07E325E0FA</VendorId>
<DocTypeId>CE3CD095580647389ED402675B43BE16</DocTypeId>
<AccNo>TXT:</AccNo>
<StmtDate>20161128</StmtDate>
<DDSDocValue name="UniqueDocID" type="text" len="32">J48309A0580113A27E053A2DEF40AC8B8</DDSDocValue>
<NumberOfPages value="8"/>
<Skipped>
<SPages></SPages>
</Skipped>
</document>
<document docID="1" docMasterID="1A5D331DDF8A84385F77B621C3F9CD86" docInstanceID="49E3D61E9CE1DF43BDD042F296913C88">
<VendorId>7618CEADE31441C99FE1BC07E325E0FA</VendorId>
<DocTypeId>CE3CD095580647389ED402675B43BE16</DocTypeId>
<AccNo>TXT:1</AccNo>
<StmtDate>20161128</StmtDate>
<DDSDocValue name="UniqueDocID" type="text" len="32">P48309A0580113A27E053A2DEF40AC8B8</DDSDocValue>
<NumberOfPages value="8"/>
<Skipped>
<SPages></SPages>
</Skipped>
</document>
</eGAD>
What I try to do is, I read the first GUID from text file and compare it with each JRNxml's document group and if I found match means, i'll replace the innertext value with text files second value.
Below is my code
static void Main()
{
//Load the File
using (StreamReader reader = new StreamReader("C:\\temp1\\AllXMLData_FinalOutput.txt"))
{
string line = reader.ReadLine();
string[] value = new string[0];
while ((line = reader.ReadLine()) != null)
{
// Load the file and read the GUID and Plan number one by one From Source Text file
var values = line.Split(',');
string GUIDfromTxt = values[0]; // Holds the GUID value from the Source Txt file
string PlanNofromTxt = values[1]; // Holds the Plan number valuse from the Source Txt file
// Read the XML's one by one from Destination folder and search for the GUID on each group
string folderPath = "C:\\Temp2";
DirectoryInfo di = new DirectoryInfo(folderPath);
FileInfo[] rgFiles = di.GetFiles("*.JRN");
foreach (FileInfo fi in rgFiles)
{
XmlDocument xmljrndoc = new XmlDocument();
XmlNodeList xmlnode;
FileStream fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite); // Open file
xmljrndoc.Load(fs);
xmlnode = xmljrndoc.GetElementsByTagName("document");
string JRNGUID = "";
string JRNPLAN = "";
for (int k = 0; k < xmlnode.Count; k++) // Read all the elements one by one
{
JRNGUID= xmlnode[k].SelectSingleNode("DDSDocValue[#name='UniqueDocID']").InnerText.Trim(); //get guid value from Destination XML
JRNPLAN= xmlnode[k].SelectSingleNode("AccNo").InnerText.Trim(); //get Plan number value from Destination XML
Console.WriteLine("Value From Text File GUID : " + GUIDfromTxt + " Plan Number : " + PlanNofromTxt);
Console.WriteLine("Value From JRN File GUID : " + JRNGUID + " Plan Number : " + JRNPLAN);
if ((GUIDfromTxt == JRNGUID) && (JRNPLAN.Length <= 8)) // check the GUID matches
{
Console.WriteLine("OLD Value : "+ JRNPLAN + " NEW Value : " + PlanNofromTxt); xmlnode[k].SelectSingleNode("AccNo").InnerText.Replace(JRNPLAN, PlanNofromTxt); // replace the txt plan to xml plan tag
}
Console.WriteLine("Xml JRN Value after find and replace " + JRNGUID + " " + JRNPLAN);
}
fs.Close();
//fs.Dispose();
}
Console.ReadKey();
}
//reader.Close();
//reader.Dispose();
}
}
This code is not working in last part means, unable to replace the text in xmlJRN file.
Can some one help me to find the mistake I have done here? you help is much appreciated. I want to replace a value and save files.
EDIT1:
Thanks for your suggestions, I've completed the code. Here is the final one.
static void Main()
{
StreamWriter sw = new StreamWriter("C:\\Temp3\\Log.txt", false, Encoding.ASCII); // log file declaration
string folderPath = "C:\\Temp2";
DirectoryInfo di = new DirectoryInfo(folderPath);
FileInfo[] rgFiles = di.GetFiles("*.JRN");
foreach (FileInfo fi in rgFiles)
{
sw.WriteLine("Opening XML JRN File : " + fi.Name);
XmlDocument xmljrndoc = new XmlDocument();
XmlNodeList xmlnode;
FileStream fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite);
xmljrndoc.Load(fs);
xmlnode = xmljrndoc.GetElementsByTagName("document");
string JRNGUID = "";
string JRNPLAN = "";
for (int k = 0; k < xmlnode.Count; k++) // Read all the elements one by one
{
JRNGUID = xmlnode[k].SelectSingleNode("DDSDocValue[#name='UniqueDocID']").InnerText.Trim(); //get guid value from Destination XML
JRNPLAN = xmlnode[k].SelectSingleNode("AccNo").InnerText.Trim();
sw.WriteLine("FROM XMLJRN file - GUID : " + JRNGUID + " PlanNumber : " + JRNPLAN);
StreamReader reader = new StreamReader("C:\\temp1\\AllXMLData_FinalOutput.txt");
sw.WriteLine("Reading Txt file for GUID Search... ");
string line = reader.ReadLine();
string[] value = new string[0];
while ((line = reader.ReadLine()) != null)
{
// Load the file and read the GUID and Plan number one by one
var values = line.Split(',');
string GUIDfromTxt = values[0]; // Holds the GUID value from the Txt file
string PlanNofromTxt = "Compass:" + values[1]; // Holds the Plan number valuse from the Txt file
sw.WriteLine("FROM text file - GUID : " + GUIDfromTxt + " PlanNumber : " + PlanNofromTxt);
if ((GUIDfromTxt == JRNGUID) && (JRNPLAN.Length <= 8)) // check the GUID matches
{
sw.WriteLine("GUID MATCH FOUND!");
sw.WriteLine("OLD Value : " + JRNPLAN + " replaced with NEW Value : " + PlanNofromTxt);
fs.Close();
FileStream fs1 = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write);
xmljrndoc.Save(#"C:\\Temp3\\" + fi.Name); // replace the txt plan to xml plan tag
fs1.Close();
// xmljrndoc.Save(fi.FullName);
}
else
{
sw.WriteLine("GUID MATCH NOT FOUND!");
}
}
}
}
sw.Close();
}
String.Replace does not actually modify the string directly. It returns a copy of the string with the replacement. You still need to assign the modified value to InnerText yourself.
For example, instead of:
xmlnode[k].SelectSingleNode("AccNo").InnerText.Replace(JRNPLAN, PlanNofromTxt);
you need to do something like:
var node = xmlnode[k].SelectSingleNode("AccNo");
node.InnerText = node.InnerText.Replace(JRNPLAN, PlanNofromTxt);
XDocument coordinates = XDocument.Load("http://feeds.feedburner.com/TechCrunch");
System.IO.StreamWriter StreamWriter1 = new System.IO.StreamWriter(DestFile);
XNamespace nsContent = "http://purl.org/rss/1.0/modules/content/";
string pchild = null;
foreach (var item in coordinates.Descendants("item"))
{
string link = item.Element("guid").Value;
//string content = item.Element(nsContent + "encoded").Value;
foreach (var child in item.Descendants(nsContent + "encoded"))
{
pchild = pchild + child.Element("p").Value;
}
StreamWriter1.WriteLine(link + Environment.NewLine + Environment.NewLine + pchild + Environment.NewLine);
}
StreamWriter1.Close();
If i use Commented line code (string content = item.Element(nsContent + "encoded").Value;) instead of inner for loop than it will fetch the value of <conten:encoded> element but it contains all links, images etc etc. And I want only text.
For that I have tried to use this filter (inner for loop) but its showing error :
Object reference not set to an instance of an object.
Please suggest me code so that I can store only text and remove all other links, <img> tags etc.
The content of item.Element(nsContent + "encoded").Value is html not xml. You should parse it accordingly, such as using Html Agility Pack
See the example below
string content = item.Element(nsContent + "encoded").Value;
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(new StringReader(content));
var text = String.Join(Environment.NewLine + Environment.NewLine,
doc.DocumentNode
.Descendants("p")
.Select(n => "\t" + System.Web.HttpUtility.HtmlDecode(n.InnerText))
);
Firstly, I would start by using a StringBuilder:
StringBuilder sb = new StringBuilder();
Then, I suspect that sometimes, the "child" doesn't have a "p" element, so you can check before using it:
foreach (var child in item.Descendants(nsContent + "encoded"))
{
if (child.Element("p") != null)
{
sb.Append(child.Element("p").Value);
}
}
StreamWriter1.WriteLine(link + Environment.NewLine + Environment.NewLine + sb.ToString() + Environment.NewLine);
Does that work for you?
I am generating HTML files on the fly, and I would like to create a PDF from the final file. I am using the following to generate the HTML file:
public static void WriteHTML(string cFile, List<Movie> mList)
{
int lineID = 0;
string strHeader, strMovie, strGenre, tmpGenre = null;
string strPDF = null;
// initiates streamwriter for catalog output file
FileStream fs = new FileStream(cFile, FileMode.Create);
StreamWriter catalog = new StreamWriter(fs);
strHeader = "<style type=\"text/css\">\r\n" + "<!--\r\n" + "tr#odd {\r\n" + " background-color:#e2e2e2;\r\n" + " vertical-align:top;\r\n" + "}\r\n" + "\r\n" + "tr#even {\r\n" + " vertical-align:top;\r\n" + "}\r\n" + "div#title {\r\n" + " font-size:16px;\r\n" + " font-weight:bold;\r\n" + "}\r\n" + "\r\n" + "div#mpaa {\r\n" + " font-size:10px;\r\n" + "}\r\n" + "\r\n" + "div#genre {\r\n" + " font-size:12px;\r\n" + " font-style:italic;\r\n" + "}\r\n" + "\r\n" + "div#plot {\r\n" + " height: 63px;\r\n" + " font-size:12px;\r\n" + " overflow:hidden;\r\n" + "}\r\n" + "-->\r\n" + "</style>\r\n" + "\r\n" + "<html>\r\n" + " <body>\r\n" + " <table>\r\n";
catalog.WriteLine(strHeader);
strPDF = strHeader;
foreach (Movie m in mList)
{
tmpGenre = null;
strMovie = lineID == 0 ? " <tr id=\"odd\" style=\"page-break-inside:avoid\">\r\n" : " <tr id=\"even\" style=\"page-break-inside:avoid\">\r\n";
catalog.WriteLine(strMovie);
strPDF += strMovie;
foreach (string genre in m.Genres)
tmpGenre += ", " + genre + "";
strGenre = tmpGenre != null ? tmpGenre.Substring(2) : null;
strMovie = " <td>\r\n" + " <img src=\".\\images\\" + m.ImageFile + "\" width=\"75\" height=\"110\">\r\n" + " </td>\r\n" + " <td>\r\n" + " <div id=\"title\">" + m.Title + "</div>\r\n" + " <div id=\"mpaa\">" + m.Certification + " " + m.MPAA + "</div>\r\n" + " <div id=\"genre\">" + strGenre + "</div>\r\n" + " <div id=\"plot\">" + m.Plot + "</div>\r\n" + " </td>\r\n" + " </tr>\r\n";
catalog.WriteLine(strMovie);
strPDF += strMovie;
lineID = lineID == 0 ? 1 : 0;
}
string closingHTML = " </table>\r\n" + " </body>\r\n" + "</html>";
catalog.WriteLine(closingHTML);
strPDF += closingHTML;
WritePDF(strPDF, cFile + ".PDF");
catalog.Close();
}
Once completed, I want to call the following function to generate the PDF file:
public static void WritePDF(string cFile, string pdfFile)
{
WkHtmlToPdfConverter w = new WkHtmlToPdfConverter();
byte[] strHTML = w.Convert(cFile);
File.WriteAllBytes(pdfFile, strHTML);
w.Dispose();
}
I've discovered that the .Convert function will convert HTML code to PDF, not a file. Secondly, when I pass in the HTML code directly, the images are not appearing in the PDF. I know there is an issue with .GIF files, but these are all .JPG files.
I've read a lot about how good wkhtmltopdf is, and the guy who wrote WkHTMLToSharp posted his project all over SO, but I've been disappointed by the lack of documentation for it.
I WANT to be able to pass in a file to convert, change the margins (I know this is possible, I just need to figure out the correct settings), have it convert images correctly, and most importantly, to not break up my items across multiple pages (support "page-break-inside:avoid" or something similar).
I'd love to see how others are using this!
I have coded an example about how to create a PDF from HTML. I just updated it to also print images.
https://github.com/hmadrigal/playground-dotnet/tree/master/MsDotNet.PdfGeneration
(In my blog post I explain most of the project https://hmadrigal.wordpress.com/2015/10/16/creating-pdf-reports-from-html-using-dotliquid-markup-for-templates-and-wkhtmltoxsharp-for-printing-pdf/ )
Pretty much you have two options:
1: Using file:// and the fullpath to the file.
<img alt="profile" src="{{ employee.PorfileFileName | Prepend: "Assets\ProfileImage\" | ToLocalPath }}" />
2: Using URL Data (https://en.wikipedia.org/wiki/Data_URI_scheme)
<img alt="profile" src="data:image/png;base64,{{ employee.PorfileFileName | Prepend: "Assets\ProfileImage\" | ToLocalPath | ToBase64 }}" />
Cheers,
Herb
Use WkHtmlToXSharp.
Download the latest DLL from Github
public static string ConvertHTMLtoPDF(string htmlFullPath, string pageSize, string orientation)
{
string pdfUrl = htmlFullPath.Replace(".html", ".pdf");
try
{
#region USING WkHtmlToXSharp.dll
//IHtmlToPdfConverter converter = new WkHtmlToPdfConverter();
IHtmlToPdfConverter converter = new MultiplexingConverter();
converter.GlobalSettings.Margin.Top = "0cm";
converter.GlobalSettings.Margin.Bottom = "0cm";
converter.GlobalSettings.Margin.Left = "0cm";
converter.GlobalSettings.Margin.Right = "0cm";
converter.GlobalSettings.Orientation = (PdfOrientation)Enum.Parse(typeof(PdfOrientation), orientation);
if (!string.IsNullOrEmpty(pageSize))
converter.GlobalSettings.Size.PageSize = (PdfPageSize)Enum.Parse(typeof(PdfPageSize), pageSize);
converter.ObjectSettings.Page = htmlFullPath;
converter.ObjectSettings.Web.EnablePlugins = true;
converter.ObjectSettings.Web.EnableJavascript = true;
converter.ObjectSettings.Web.Background = true;
converter.ObjectSettings.Web.LoadImages = true;
converter.ObjectSettings.Load.LoadErrorHandling = LoadErrorHandlingType.ignore;
Byte[] bufferPDF = converter.Convert();
System.IO.File.WriteAllBytes(pdfUrl, bufferPDF);
converter.Dispose();
#endregion
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return pdfUrl;
}
You can use Spire.Pdf to do so.
This component could convert html to pdf.
PdfDocument pdfdoc = new PdfDocument();
pdfdoc.LoadFromHTML(fileFullName, true, true, true);
//String url = "http://www.e-iceblue.com/";
//pdfdoc.LoadFromHTML(url, false, true, true);
pdfdoc.SaveToFile("FromHTML.pdf");
We're also using wkhtmltopdf and are able to render images correctly. However, by default the rendering of images is disabled.
You have to specify those options on your converter instance:
var wk = _GetConverter()
wk.GlobalSettings.Margin.Top = "20mm";
wk.GlobalSettings.Margin.Bottom = "10mm";
wk.GlobalSettings.Margin.Left = "10mm";
wk.GlobalSettings.Margin.Right = "10mm";
wk.GlobalSettings.Size.PaperSize = PdfPaperSize.A4;
wk.ObjectSettings.Web.PrintMediaType = true;
wk.ObjectSettings.Web.LoadImages = true;
wk.ObjectSettings.Web.EnablePlugins = false;
wk.ObjectSettings.Web.EnableJavascript = true;
result = wk.Convert(htmlContent);