System.Xml.XPath.XPathException: 'Unclosed chain.' - c#

I am trying to get an information from the web (adress in my code) with HtmlAgilityPack in C#, but I have to wait until the <div class="center fs22 green lh32"> is loaded on the page.
var url = $"https://www.webpage.com/test{info}";
var web = new HtmlWeb();
var doc = web.LoadFromBrowser(url, html =>
{
return !html.Contains("<div class=\"center fs22 green lh32\"></div>");
});
string adress = doc.DocumentNode
.SelectSingleNode("//td/span[#id='testedAddress")
.Attributes["value"].Value;
Unfortunally I always get this error when I start my code :
Translation : 'Unclosed chain.'
How can I pass this error ?

The error occurs on the following line:
.SelectSingleNode("//td/span[#id='testedAddress")
There is a ' and a ] missing at the end of that XPath expression. That inner part incompletely enclosed in ' is the "chain" (actually, a string in English, or "chaîne de caractères" in French) the error message is talking about.
So, the line should read instead:
.SelectSingleNode("//td/span[#id='testedAddress']")

Related

Set a Json Serialized Object into session. not able to parse it from the View

Just the Brief Code which is enough to explain my problem i guess.
Here is my c# code:
List<MaZone> ListZoneValues = new List<MaZone>();
ListZoneValues.Add(new MaZone()
{
ZoneIc = int.Parse(DataReader["ZoneIC"].ToString()),
ZoneName = DataReader["ZoneName"].ToString()
});
HttpContext.Session.SetString("ZoneDetails",JsonConvert.SerializeObject(ListZoneValues));
Here is my javascript code.
var ZoneDetailsVB = '#HttpContextAccessor.HttpContext.Session.GetString("ZoneDetails")';
JSON.parse(ZoneDetailsVB);
But the error im face is while Parsing the Json.
The Error was:
Uncaught SyntaxError: Unexpected token & in JSON at position 2
at JSON.parse (<anonymous>)
Json string Recieved:
[{"ZoneIc":1,"ZoneName":"Zone1"},{"ZoneIc":2,"ZoneName":"Zone1 & 2"},{"ZoneIc":3,"ZoneName":"Zone2"},{"ZoneIc":4,"ZoneName":"Zone4"},{"ZoneIc":5,"ZoneName":"Zone5"},{"ZoneIc":6,"ZoneName":"Zone 6"},{"ZoneIc":7,"ZoneName":"Zone Num 7"}]
Thanks in Advance.
If you are using jQuery, you could do something like this
function htmlDecode(value) {
return $("<textarea/>").html(value).text();
}
var ZoneDetailsVB = '#HttpContextAccessor.HttpContext.Session.GetString("ZoneDetails")';
JSON.parse(htmlDecode(ZoneDetailsVB));
You can also use he library https://github.com/mathiasbynens/he
Third solution is to use
Html.Raw
var ZoneDetailsVB = '#(Html.Raw(HttpContextAccessor.HttpContext.Session.GetString("ZoneDetails").ToString()))'

How to create HTML page by code [duplicate]

How would I open a new window in JavaScript and insert HTML data instead of just linking to an HTML file?
I would not recomend you to use document.write as others suggest, because if you will open such window twice your HTML will be duplicated 2 times (or more).
Use innerHTML instead
var win = window.open("", "Title", "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=200,top="+(screen.height-400)+",left="+(screen.width-840));
win.document.body.innerHTML = "HTML";
You can use window.open to open a new window/tab(according to browser setting) in javascript.
By using document.write you can write HTML content to the opened window.
When you create a new window using open, it returns a reference to the new window, you can use that reference to write to the newly opened window via its document object.
Here is an example:
var newWin = open('url','windowName','height=300,width=300');
newWin.document.write('html to write...');
Here's how to do it with an HTML Blob, so that you have control over the entire HTML document:
https://codepen.io/trusktr/pen/mdeQbKG?editors=0010
This is the code, but StackOverflow blocks the window from being opened (see the codepen example instead):
const winHtml = `<!DOCTYPE html>
<html>
<head>
<title>Window with Blob</title>
</head>
<body>
<h1>Hello from the new window!</h1>
</body>
</html>`;
const winUrl = URL.createObjectURL(
new Blob([winHtml], { type: "text/html" })
);
const win = window.open(
winUrl,
"win",
`width=800,height=400,screenX=200,screenY=200`
);
You can open a new popup window by following code:
var myWindow = window.open("", "newWindow", "width=500,height=700");
//window.open('url','name','specs');
Afterwards, you can add HTML using both myWindow.document.write(); or myWindow.document.body.innerHTML = "HTML";
What I will recommend is that first you create a new html file with any name.
In this example I am using
newFile.html
And make sure to add all content in that file such as bootstrap cdn or jquery, means all the links and scripts. Then make a div with some id or use your body and give that a id. in this example I have given id="mainBody" to my newFile.html <body> tag
<body id="mainBody">
Then open this file using
<script>
var myWindow = window.open("newFile.html", "newWindow", "width=500,height=700");
</script>
And add whatever you want to add in your body tag. using following code
<script>
var myWindow = window.open("newFile.html","newWindow","width=500,height=700");
myWindow.onload = function(){
let content = "<button class='btn btn-primary' onclick='window.print();'>Confirm</button>";
myWindow.document.getElementById('mainBody').innerHTML = content;
}
myWindow.window.close();
</script>
it is as simple as that.
You can also create an "example.html" page which has your desired html and give that page's url as parameter to window.open
var url = '/example.html';
var myWindow = window.open(url, "", "width=800,height=600");
Use this one. It worked for me very perfect.
For New window:
new_window = window.open(URL.createObjectURL(new Blob([HTML_CONTENT], { type: "text/html" })))
for pop-up
new_window = window.open(URL.createObjectURL(new Blob([HTML_CONTENT], { type: "text/html" })),"width=800,height=600")
Replace HTML_CONTENT with your own HTML Code
Like:
new_window = window.open(URL.createObjectURL(new Blob(["<h1>Hello</h1>"], { type: "text/html" })))
if your window.open() & innerHTML works fine, ignore this answer.
following answer only focus on cross-origin access exception
#key-in_short,workaround:: [for cross-origin access exception]
when you exec code in main.html -- which tries to access file window_ImageGallery.html by using window.open() & innerHTML
for anyone who encounter cross-origin access exception
and you dont want to disable/mess_around_with Chrome security policy
-> you may use query string to transfer the html code data, as a workaround.
#details::
#problem-given_situation,#problem-arise_problem::
say you exec following simple window.open command as other answer suggested.
let window_Test = window.open('window_ImageGallery.html', 'Image Enlarged Window' + $(this).attr('src'), 'width=1000,height=800,top=50,left=50');
window_Test.document.body.innerHTML = 'aaaaaa';
you may encounter following cross-origin access exception
window_Test.document.body.innerHTML = 'aaaaaa'; // < Exception here
Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.
=> #problem-solution-workaround::
you may use query string to transfer the html code data, as a workaround. <- Transfer data from one HTML file to another
#eg::
in your main.html
// #>> open ViewerJs in a new html window
eleJq_Img.click(function() {
// #>>> send some query string data -- a list of <img> tags, to the new html window
// #repeat: must use Query String to pass html code data, else you get `Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.` (cross origin access issue)
let id_ThisImg = this.id;
let ind_ThisImg = this.getAttribute('data-index-img');
let url_file_html_window_ImageGallery = 'window_ImageGallery.html'
+ '?queryStr_html_ListOfImages=' + encodeURIComponent(html_ListOfImages)
+ '&queryStr_id_ThisImg=' + encodeURIComponent(id_ThisImg)
+ '&queryStr_ind_ThisImg=' + encodeURIComponent(ind_ThisImg);
// #>>> open ViewerJs in a new html window
let window_ImageGallery = window.open(url_file_html_window_ImageGallery, undefined, 'width=1000,height=800,top=50,left=50');
});
in your window_ImageGallery.html
window.onload = function () {
// #>> get parameter from URL
// #repeat: must use Query String to pass html code data, else you get `Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.` (cross origin access issue)
// https://stackoverflow.com/questions/17502071/transfer-data-from-one-html-file-to-another
let data = getParamFromUrl();
let html_ListOfImages = decodeURIComponent(data.queryStr_html_ListOfImages);
let id_ThisImgThatOpenedTheHtmlWindow = decodeURIComponent(data.queryStr_id_ThisImg);
let ind_ThisImgThatOpenedTheHtmlWindow = decodeURIComponent(data.queryStr_ind_ThisImg);
// #>> add the Images to the list
document.getElementById('windowImageGallery_ContainerOfInsertedImages').innerHTML = html_ListOfImages;
// -------- do your stuff with the html code data
};
function getParamFromUrl() {
let url = document.location.href;
let params = url.split('?')[1].split('&');
let data = {};
let tmp;
for (let i = 0, l = params.length; i < l; i++) {
tmp = params[i].split('=');
data[tmp[0]] = tmp[1];
}
return data
}
#minor-note::
(seems) sometimes you may not get the cross-origin access exception
due to, if you modify the html of 'window_ImageGallery.html' in main.html before window_ImageGallery.html is loaded
above statement is based on my test
& another answer -- window.open: is it possible open a new window with modify its DOM
if you want to make sure to see that Exception,
you can try to wait until the opening html window finish loading, then continue execute your code
#eg::
use defer() <- Waiting for child window loading to complete
let window_ImageGallery = window.open('window_ImageGallery.html', undefined, 'width=1000,height=800,top=50,left=50');
window_ImageGallery.addEventListener("unload", function () {
defer(function (){
console.log(window_ImageGallery.document.body); // < Exception here
});
});
function defer (callback) {
var channel = new MessageChannel();
channel.port1.onmessage = function (e) {
callback();
};
channel.port2.postMessage(null);
}
or use sleep() with async What is the JavaScript version of sleep()?
eleJq_Img.click(async function() {
...
let window_Test = window.open( ...
...
await new Promise(r => setTimeout(r, 2000));
console.log(window_Test.document.body.innerHTML); // < Exception here
});
or you get null pointer exception
if you try to access elements in window_ImageGallery.html
#minor-comment::
There are too many similar Posts about the cross-origin issue. And there are some posts about window.open()
Idk which post is the best place to place the answer. And I picked here.

xPath is wrong given by the Browser or HTMLAgilityPack cannot use xPath?

I'm trying to get all languages from Google Translate. When I Open Developer Tools and click one of the language when all languages are popped (when arrow clicked), It gives //*[#id=':7']/div/text() for Arabic, but it returns null when I try to get node:
async Task AddLanguages()
{
try
{
// //*[#id=":6"]/div/text()
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
for (int i = 6; i <= 9; i++)
{
//*[#id=":6"]/div/text() //*[#id=":6"]/div/div
Debug.WriteLine(i);
var element = document.DocumentNode.SelectSingleNode("//*[#id=':7']/div/text()");
Trace.WriteLine(element == null, "Element is null");
}
}
catch (Exception e)
{
this.ShowMessageAsync("Hata!", "Dilleri yüklerken hata ortaya çıktı.");
}
}
Element is null: True outputs all the times ( I was trying to use for loop to loop through languages but, it doesnt even work for single one!)
I guess your xpath is wrong. You can try something like:
string Url = "https://translate.google.com/";
HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load(Url);
var arabic = doc.DocumentNode.Descendants("div").FirstOrDefault(_ => _.ChildNodes.Any(node => node.Name.Equals("#text") && node.InnerText.Equals("Arabic")));
Since I can't comment yet...Have you tried clicking on the dropdwon first before looking for the elements?
Clicking on //*[#id='gt-sl-gms'] or it's inner div would make the elements visible..
That should work..
Anyway, I can't make $x work for the console in google chrome. I'm getting an Uncaught Type Error currently. Not sure if that has to do with anything..
Edit: Oh wait i think I know your problem..upon closer inspection of the element, it seems that the element (div) has another div before the text. so try /*[#id=':7']/div/text()[2]

Xelement tags issue

enter code herehey guys im having trouble with xelement when im trying to open the test page an unhandled exception appears and that because the tag doesn't match the closing in another line i tried to add the closings tag but the error happens before the adding function could work
test page http://densetsu.org/PP2012/benchmark1.html
so is there is a way to pass the tag problems without losing the tag effect
this is the main code:
XElement tree = XElement.Load(toolStripTextBox1.Text);
String s = tree.ToString();
textBox1.Text = String_dealer.addmissing(s);
this is the string changer
public static String addmissing(String txt)
{
if (txt.Contains("<br>") || (txt.Contains("</br>")))
{
txt.Replace("<br>", "<br></br>");
txt.Replace("</br>", "<br></br>");
}
else if (txt.Contains("<hr>") || (txt.Contains("</hr>")))
{
txt.Replace("<hr>", "<hr> </hr>");
txt.Replace("</hr>", "<hr> </hr>");
}
return txt;
}
and the problem text :
An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll
Additional information: The 'hr' start tag on line 8 does not match the end tag of 'br'. Line 9, position 10.
using a stream reader from a web request then storing the stream into an String file after that you can pass the string to sgml.reader which will transform the html into valid xml

C# Html Agility Pack ( SelectSingleNode )

I'm trying to parse this field, but can't get it to work. Current attempt:
var name = doc.DocumentNode.SelectSingleNode("//*[#id='my_name']").InnerHtml;
<h1 class="bla" id="my_name">namehere</h1>
Error: Object reference not set to an instance of an object.
Appreciate any help.
#John - I can assure that the HTML is correctly loaded. I am trying to read my facebook name for learning purposes. Here is a screenshot from the Firebug plugin. The version i am using is 1.4.0.
http://i54.tinypic.com/kn3wo.jpg
I guess the problem is that profile_name is a child node or something, that's why I'm not able to read it?
The reason your code doesn't work is because there is JavaScript on the page that is actually writing out the <h1 id='profile_name'> tag, so if you're requesting the page from a User Agent (or via AJAX) that doesn't execute JavaScript then you won't find the element.
I was able to get my own name using the following selector:
string name =
doc.DocumentNode.SelectSingleNode("//a[#id='navAccountName']").InnerText;
Try this:
var name = doc.DocumentNode.SelectSingleNode("//#id='my_name'").InnerHtml;
HtmlAgilityPack.HtmlNode name = doc.DocumentNode.SelectSingleNode("//h1[#id='my_name']").InnerText;
public async Task<List<string>> GetAllTagLinkContent(string content)
{
string html = string.Format("<html><head></head><body>{0}</body></html>", content);
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
var nodes = doc.DocumentNode.SelectNodes("//[#id='my_name']");
return nodes.ToList().ConvertAll(r => r.InnerText).Select(j => j).ToList();
}
It's ok with ("//a[#href]"); You can try it as above.Hope helpful

Categories