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):
}
}
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)
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);
}
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.
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];