How to store links in DB number wise? - c#

This is my code,
HtmlNodeCollection categorynode = null;
categorynode = doc.DocumentNode.SelectNodes("//div[#class='parentMenu arrow']");//"//div[#class='drop-menu']//a[#href]"
if (categorynode != null)
{
foreach (HtmlNode Node in categorynode)
{
string Html = Node.InnerHtml;
if (Html != null)
{
HtmlDocument Node2 = new HtmlDocument();
Node2.LoadHtml(Html);
foreach (HtmlNode link in Node2.DocumentNode.SelectNodes("//a"))
{
HtmlAttribute att = link.Attributes["href"];
Console.WriteLine(new Regex(#"(?<=[\?&]id=)\d+(?=\&|\#|$)").Match(att.Value).Value);
string Links = att.Value;
Modelclass _ms = new Modelclass();
_ms.link = Links;
_ms.Name = "Apple";
_ms.CID = 0;
_ms.Type = "Categories";
Controller cc = new Controller();
cc.InsertCategories(_ms);
}
}
}
I have tables in my DB were I have set an ID as a primary key but when I store all these links in DB it should be sorted but it is like 1 2 3 9 7 6 ,
is there something wrong with my code or what should i do please guide me

keep an ID in your table where you are storing your links and set ID to auto increment that will help may be

Related

How to Read XML element with namespace value

I am facing problem in fetching xml element value if it is having name space. please help me what is the problem here. My xml string is below
<PurchaseOrder xmlns:aw="http://www.adventure-works.com"> <aw:ShippingAddress> <aw:Name>John</aw:Name> <aw:Street>123 Main St.</aw:Street> <aw:City>Seattle</aw:City> <aw:State>WA</aw:State> <aw:Zip>98113</aw:Zip> <aw:Country>USA</aw:Country> </aw:ShippingAddress> <aw:ShippingAddress> <aw:Name>Chris Preston</aw:Name> <aw:Street>123 Robin St.</aw:Street> <aw:City>Newyork</aw:City> <aw:State>TU</aw:State> <aw:Zip>98113</aw:Zip> <aw:Country>USA</aw:Country> </aw:ShippingAddress> <aw:ShippingAddress> <aw:Name>Charlis</aw:Name> <aw:Street>53 Jacob St.</aw:Street> <aw:City>California</aw:City> <aw:State>DOWNTOWN</aw:State> <aw:Zip>98111</aw:Zip> <aw:Country>USA</aw:Country> </aw:ShippingAddress> </aw:PurchaseOrder>
my code is below
XDocument doc = XDocument.Load("PurchaseOrder.xml");
List<PurchaseOrder> listWO = new List<PurchaseOrder>();
foreach (XElement el in doc.Root.Elements())
{
if ( el.Elements().Count() > 0)
{
PurchaseOrder po = new PurchaseOrder
{
Name = el.Elements("aw:Name").First().Value,
City = el.Elements("aw:City").First().Value,
Country = el.Elements("aw:Country").First().Value
};
listPO.Add(po):
}
}
Here i am not getting the value of each "ShippingAddress" wise.
See changes below :
XDocument doc = XDocument.Load("PurchaseOrder.xml");
XNamespace awNs = doc.Root.GetNamespaceOfPrefix("aw");
List<PurchaseOrder> listWO = new List<PurchaseOrder>();
foreach (XElement el in doc.Root.Elements())
{
if ( el.Elements().Count() > 0)
{
PurchaseOrder po = new PurchaseOrder
{
Name = el.Elements(awNs + "Name").First().Value,
City = el.Elements(awNs + "City").First().Value,
Country = el.Elements(awNs + "Country").First().Value
};
listPO.Add(po):
}
}

Syntax error in HAP SetAttributeValue or mistake in code

imgs = doc.DocumentNode.SelectNodes("//img");
HtmlNode img in imgs
string imageIdString = image.Id.ToString();
img.SetAttributeValue("src", "/ImageBrowser/ImageById/" + imageIdString);
I get a proper value for the ID, but the img source stays unchanged and I can't find why
tried to manage it like here:
Need to replace an img src attrib with new value
Edit1: The requested code
string input = sectionEditModel.Content;
string htmlstring = sectionEditModel.Content;
string htmlstringdecoded = HttpUtility.HtmlDecode(htmlstring);
HtmlDocument doc = new HtmlDocument();
List<string> urls = new List<string>();
DbImgBrowser.Models.Image image = null;
doc.LoadHtml(htmlstringdecoded);
var files = new FilesRepository();
HtmlNodeCollection imgs = new HtmlNodeCollection(doc.DocumentNode);
imgs = doc.DocumentNode.SelectNodes("//img");
if (imgs != null && imgs.Count > 0)
{
foreach (HtmlNode img in imgs)
{
HtmlAttribute srcs = img.Attributes[#"src"];
urls.Add(srcs.Value);
{
foreach (string Value in urls){
string AttrVal = img.GetAttributeValue("src", null);
if(AttrVal.Contains("base64"))
{
byte[] data = Convert.FromBase64String(Value.Substring(Value.IndexOf(",") + 1));
var pFolder = files.GetFolderByPath(string.Empty);
if (pFolder != null)
{
image = new DbImgBrowser.Models.Image()
{
Name = Guid.NewGuid().ToString(),
Folder = pFolder,
Image1 = data
};
files.Db.Images.Add(image);
files.Db.SaveChanges();
string imageIdString = image.Id.ToString();
img.SetAttributeValue("src", "/ImageBrowser/ImageById/" + imageIdString);
files.Db.SaveChanges();
}
}
Edit2: Example paths: before base64 example image
Path by Url example /ImageBrowser/Image?path=Test2.PNG
Wanted Result src="ImageBrowser/ImageById/"ID" (1-1000)
Edit3: Still all src is not changed
The answer is very simple.
I was on a local doc but I had to return it to the content and save the section
SectionsRepository.SaveSection(Section sec)

How to get a text between nodes

I have a problem with extracting text between nodes.It shows me the entire span node.I would like to get value of hours e.g 4:45;5:15 e.t.c.
var html = #"https://programtv.onet.pl/";
HtmlWeb web = new HtmlWeb();
var htmldoc=web.Load(html);
var findhours = htmldoc.DocumentNode.SelectNodes("//div[#id='boxTV1']//div[#class='hours']//span[#class='hour']");
if (findhours != null)
{
foreach (var x in findhours )
{
Console.WriteLine(x.OuterHtml);
}
}
else
{
Console.WriteLine("node = null");
}
Console.ReadLine();
Application window
You can simply use the InnerText property of your HtmlNode object. Checkout the following documentation.
foreach (var x in findhours )
{
Console.WriteLine(x.InnerText);
}

For Loop in Decendents (Sequence contains no Element ) c#

I have a complex XML file where I want to retrieve values from specific transaction tag.At the end, i need to take the values to a CSV file.
I am trying to retrieve the value of below in each transaction tags where it is present.
<szCustomerID>2988880562567</szCustomerID>
<szCustomerName>130808125028SHM </szCustomerName>
<szExternalID>3177#06/07/17</szExternalID>
Note that all transaction tag is not the same
Unfortunately it is looping through all transaction tags and i am getting error sequence contains no element
Is there a way i can loop withing the Descendants and always skip the second transaction tag since i won't be needing it
try
{
string strSource_voucher = #"C:\\TempFid";
string[] files = Directory.GetFiles(strSource_voucher, "*.xml", SearchOption.AllDirectories);
if (files.Length > 0) // Check if files has values
{
StringBuilder dataToBeWritten = new StringBuilder();
foreach (string file in files)
{
dataToBeWritten.Append("szCustomerID");
dataToBeWritten.Append(",");
dataToBeWritten.Append("szCustomerName");
dataToBeWritten.Append(",");
dataToBeWritten.Append("szExternalID");
dataToBeWritten.Append(",");
dataToBeWritten.Append(Environment.NewLine);
XDocument xDocument = XDocument.Load(file);
int results = xDocument.Descendants("Transaction").Count();
foreach (var trans in xDocument.Descendants("Transaction"))
{
//var trans = xDocument.Descendants("Transaction");
var val1 = (string)trans.Descendants("Set").Elements("szCustomerID").First();
var val2 = (string)trans.Descendants("Set").Elements("szCustomerName").First();
var val3 = (string)trans.Descendants("Set").Elements("szExternalID").First();
dataToBeWritten.Append(val1);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val2);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val3);
dataToBeWritten.Append(",");
dataToBeWritten.Append(Environment.NewLine);
} // End of For each var trans
Console.WriteLine(dataToBeWritten.ToString());
Console.ReadLine();
You can use Element instead of Elements and check if the value is not null
foreach (var trans in xDocument.Descendants("Transaction"))
{
XElement setElement = trans.Descendants("Set").FirstOrDefault();
if (setElement != null)
{
var val1 = (string)setElement.Element("szCustomerID");
var val2 = (string)setElement.Element("szCustomerName");
var val3 = (string)setElement.Element("szExternalID");
if (val1 != null && val3 != null && val3 != null)
{
dataToBeWritten.Append(val1);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val2);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val3);
dataToBeWritten.Append(",");
dataToBeWritten.Append(Environment.NewLine);
}
}
}
Just use for loop and increasei by 2 like this:
var transactions = xDocument.Descendants("Transaction").ToList();
for (int i = 0; i < transactions.Count(); i += 2)
{
//var trans = xDocument.Descendants("Transaction");
var val1 = (string)transactions[i].Descendants("Set").Elements("szCustomerID").First();
var val2 = (string)transactions[i].Descendants("Set").Elements("szCustomerName").First();
var val3 = (string)transactions.Descendants("Set").Elements("szExternalID").First();
dataToBeWritten.Append(val1);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val2);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val3);
dataToBeWritten.Append(",");
dataToBeWritten.Append(Environment.NewLine);
} // End of For each var trans
There is another way to do this type of conversion, if you are open to use library (Cinchoo ETL - An open source ETL lib)
Stream based, fast to convert any xml to csv format with few lines of codes.
I believe you want to product CSV file from your xml having CUSTOMER table elements only.
Here is how you can do with this library
using (var parser = new ChoXmlReader("sample.xml").WithXPath("/UpdateDB/Transaction")
.WithField("Table", xPath: "/Insert/Table")
.WithField("szCustomerID", xPath: "/Insert/Set/szCustomerID")
.WithField("szCustomerName", xPath: "/Insert/Set/szCustomerName")
.WithField("szExternalID", xPath: "/Insert/Set/szExternalID")
)
{
using (var writer = new ChoCSVWriter("sample.csv").WithFirstLineHeader())
writer.Write(parser.Where(r => r.Table == "CUSTOMER").Select(r => new { szCustomerID = r.szCustomerID, szCustomerName = r.szCustomerName, szExternalID = r.szExternalID }));
}
The output will look as below
szCustomerID,szCustomerName,szExternalID
2988880562567,130808125028SHM,3177#06/07/17
12345,130808125028SHM,3177#06/07/17
UPDATE:
In order to split the szExternalID into 2 columns (szExternalID, szExternalDate), you will have to use the valueconverter to parse and load them. Sample shows how
using (var parser = new ChoXmlReader("sample.xml").WithXPath("/UpdateDB/Transaction")
.WithField("Table", xPath: "/Insert/Table")
.WithField("szCustomerID", xPath: "/Insert/Set/szCustomerID")
.WithField("szCustomerName", xPath: "/Insert/Set/szCustomerName")
.WithField("szExternalID", xPath: "/Insert/Set/szExternalID", valueConverter: (v) => ((string)v).Split('#')[0])
.WithField("szExternalDate", xPath: "/Insert/Set/szExternalID", valueConverter: (v) => ((string)v).Split('#')[1])
)
{
using (var writer = new ChoCSVWriter("sample.csv").WithFirstLineHeader())
writer.Write(parser.Where(r => r.Table == "CUSTOMER").Select(r => new { szCustomerID = r.szCustomerID, szCustomerName = r.szCustomerName, szExternalID = r.szExternalID, szExternalDate = r.szExternalDate }));
}
The new output will look as below
szCustomerID,szCustomerName,szExternalID,szExternalDate
2988880562567,130808125028SHM,3177,06/07/17
12345,130808125028SHM,3177,06/07/17
Disclosure: I'm the author of this library.

scraping 3rd node using htmlagilitypack

In a webpage there are several nodes having class='inner'. But i need to the 3rd node having class='inner'. If i use
string x = textBox1.Text;
string q = "";
HtmlWeb web = new HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = web.Load("myweb_link" + x);
HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//div[#class='inner']");
if (nodes != null)
{
foreach (HtmlNode n in nodes)
{
q = n.InnerText;
q = System.Net.WebUtility.HtmlDecode(q);
q = q.Trim();
MessageBox.Show(q);
}
}
else
MessageBox.Show("nothing found ");
it gives me all the nodes having class='inner'. i also know that.
But i want only the 3rd node. How can i get that???
Get the third node from the nodes variable using the indexer:
var thirdNode = nodes[2];

Categories

Resources