Get string data Xpath - c#

I need help to get data from the site. I use geckofx in my application. I want it to retrieve text data from the xpath location after loading the page
XPathResult xpathResult = geckoWebBrowser1.Document.EvaluateXPath("/html/body/table[3]/tbody/tr[1]/td[2]/a[1]");
IEnumerable<GeckoNode> foundNodes = xpathResult.GetNodes();
How to download data as text?

It looks like you are struggling to retrieve the text from the GeckoFX objects.
Here are a few calls and operations that should get you started:
//get by XPath
XPathResult xpathResult = _browser.Document.EvaluateXPath("//*[#id]/div/p[2]");
var foundNodes = xpathResult.GetNodes();
foreach (var node in foundNodes)
{
var x = node.TextContent; // get text text contained by this node (including children)
GeckoHtmlElement element = node as GeckoHtmlElement; //cast to access.. inner/outerHtml
string inner = element.InnerHtml;
string outer = element.OuterHtml;
//iterate child nodes
foreach (var child in node.ChildNodes)
{
}
}
//get by id
GeckoHtmlElement htmlElementById = _browser.Document.GetHtmlElementById("mw-content-text");
//get by tag
GeckoElementCollection byTag = _browser.Document.GetElementsByTagName("input");
foreach (var ele in byTag)
{
var y = ele.GetAttribute("value");
}
//get by class
var byClass = _browser.Document.GetElementsByClassName("input");
foreach (var node in byClass)
{
//...
}
//cast to a different object
var username = ((GeckoInputElement)_browser.Document.GetHtmlElementById("yourUsername")).Value;
//create new object from DomObject
var button = new GeckoButtonElement(_browser.Document.GetElementById("myBtn").DomObject);

public string extract(string xpath, string type)
{
string result = string.Empty;
GeckoHtmlElement elm = null;
GeckoWebBrowser wb = geckoWebBrowser1;//(GeckoWebBrowser)GetCurrentWB();
if (wb != null)
{
elm = GetElement(wb, xpath);
if (elm != null)
//UpdateUrlAbsolute(wb.Document, elm);
if (elm != null)
{
switch (type)
{
case "html":
result = elm.OuterHtml;
break;
case "text":
if (elm.GetType().Name == "GeckoTextAreaElement")
{
result = ((GeckoTextAreaElement)elm).Value;
}
else
{
result = elm.TextContent.Trim();
}
break;
case "value":
result = ((GeckoInputElement)elm).Value;
break;
default:
result = extractData(elm, type);
break;
}
}
}
return result;
}
private string extractData(GeckoHtmlElement ele, string attribute)
{
var result = string.Empty;
if (ele != null)
{
var tmp = ele.GetAttribute(attribute);
/*if (tmp == null)
{
tmp = extractData(ele.Parent, attribute);
}*/
if (tmp != null)
result = tmp.Trim();
}
return result;
}
private object GetCurrentWB()
{
if (tabControl1.SelectedTab != null)
{
if(tabControl1.SelectedTab.Controls.Count > 0)
//if (tabControl1.SelectedTab.Controls.Count > 0)
{
Control ctr = tabControl1.SelectedTab.Controls[0];
if (ctr != null)
{
return ctr as object;
}
}
}
return null;
}
private GeckoHtmlElement GetElement(GeckoWebBrowser wb, string xpath)
{
GeckoHtmlElement elm = null;
if (xpath.StartsWith("/"))
{
if (xpath.Contains("#class") || xpath.Contains("#data-type"))
{
var html = GetHtmlFromGeckoDocument(wb.Document);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var node = doc.DocumentNode.SelectSingleNode(xpath);
if (node != null)
{
var currentXpath = "/" + node.XPath;
elm = (GeckoHtmlElement)wb.Document.EvaluateXPath(currentXpath).GetNodes().FirstOrDefault();
}
}
else
{
elm = (GeckoHtmlElement)wb.Document.EvaluateXPath(xpath).GetNodes().FirstOrDefault();
}
}
else
{
elm = (GeckoHtmlElement)wb.Document.GetElementById(xpath);
}
return elm;
}
private string GetHtmlFromGeckoDocument(GeckoDocument doc)
{
var result = string.Empty;
GeckoHtmlElement element = null;
var geckoDomElement = doc.DocumentElement;
if (geckoDomElement is GeckoHtmlElement)
{
element = (GeckoHtmlElement)geckoDomElement;
result = element.InnerHtml;
}
return result;
}
private void button5_Click(object sender, EventArgs e)
{
var text = extract("/html/body/table[3]/tbody/tr[1]/td[2]/a[2]", "text");
MessageBox.Show(text);
}
I also insert the code from which I used a little longer code but it also works. maybe someone will need it. The creator of the code is Đinh Công Thắng, Web Automation App,
Regards

Related

Get Connected Elements in Autodesk Inventor via API

We have Autodesk Inventor and created a C# Addon.
In this we loop through all Objects like this:
foreach (CurrencyAPIv2.IAssetInstance s in objects)
{
var c = s.NativeObject as ComponentOccurrence;
}
How can we get the connected Object of an Object (the one which is snapped to it). And also the Info to which connector it is connected (snapped)
Michael Navara:
Can you be more specific? CurrencyAPIv2.IAssetInstance is not a member of Inventor API
using CurrencyAPIv2 = Autodesk.Factory.PublicAPI.Currency.v2;
We solved it with the XML-files which can also be watched in AttributeHelper:
void LoadConnectors(Document document, List<ConnectionElement> connections, List<ConnectedComponent> components)
{
var am = document.AttributeManager;
var d = new Dictionary<string, string>();
var entities = am.FindObjects("*", "*");
foreach (var e in entities)
{
try
{
dynamic o = e;
foreach (AttributeSet attrS in o.AttributeSets)
{
foreach (Inventor.Attribute a in attrS)
{
d.Add(o.Name, a.Value as string);
}
}
}
catch(Exception)
{ }
}
foreach (var element in d)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(element.Value);
var connectionNodes = xmlDoc.SelectNodes("//ObjectData[#Type='42']");
var componentNodes = xmlDoc.SelectNodes("//ObjectData[#Type='38']");
// Verbindungen
if (connectionNodes.Count > 0)
{
var link1Node = xmlDoc.SelectSingleNode("//ObjectData/Link1") as XmlElement;
var link2Node = xmlDoc.SelectSingleNode("//ObjectData/Link2") as XmlElement;
var connection = new ConnectionElement();
connection.Name = element.Key;
connection.Link1 = link1Node.GetAttribute("VAL");
connection.Link2 = link2Node.GetAttribute("VAL");
connections.Add(connection);
}
// Komponenten
else if (componentNodes.Count > 0)
{
var componentConnectorNodes = xmlDoc.SelectNodes("//ObjectData/Connector");
var componentConnectors = new List<ComponentConnector>();
foreach (XmlNode cc in componentConnectorNodes)
{
var idNode = cc.SelectSingleNode("Id") as XmlElement;
var displayNameNode = cc.SelectSingleNode("DisplayName") as XmlElement;
var connector = new ComponentConnector();
connector.DisplayName = displayNameNode.GetAttribute("VAL");
connector.Id = idNode.GetAttribute("VAL");
componentConnectors.Add(connector);
}
if (components.FirstOrDefault(x => x.Name == element.Key) != null)
{
components.FirstOrDefault(x => x.Name == element.Key).Connectors.AddRange(componentConnectors);
}
else
{
var component = new ConnectedComponent();
component.Name = element.Key;
component.Connectors = new List<ComponentConnector>();
component.Connectors.AddRange(componentConnectors);
components.Add(component);
}
}
}
}

Converting GeoJSON response to FeatureCollection

Hi I am trying to parse the response from a OSM webservice into feature collection using GeoJson.Net
I am new to GeoJSON and not able to identify how to do so:
The Json response can be find here. The code I have written is:
System.IO.StreamReader file = new System.IO.StreamReader(filepath);
string content = file.ReadToEnd();
file.Close();
dynamic deserialized = JsonConvert.DeserializeObject(content);
List<Feature> lstGeoLocation = new List<Feature>();
foreach (JObject item in deserialized.features)
{
//var feature = new Feature();
var geom = item.Property("geometry").Value;
}
But this will be plain JSON parsing and there might be a better way to parse the same.
I also tried NetTopologySuite JSON extension but when i use following code it gives me exception
"Expected token 'type' not found."
System.IO.StreamReader file = new System.IO.StreamReader(filepath);
string content = file.ReadToEnd();
file.Close();
var reader = new NetTopologySuite.IO.GeoJsonReader();
var featureCollection = reader.Read <NetTopologySuite.Features.FeatureCollection>(content);
I hate to answer my I question but after two days of hit & trial I get it working with both NetTopology and GeoJson
// get the JSON file content
var josnData = File.ReadAllText(destinationFileName);
// create NetTopology JSON reader
var reader = new NetTopologySuite.IO.GeoJsonReader();
// pass geoJson's FeatureCollection to read all the features
var featureCollection = reader.Read<GeoJSON.Net.Feature.FeatureCollection>(josnData);
// if feature collection is null then return
if (featureCollection == null)
{
return;
}
// loop through all the parsed featurd
for (int featureIndex = 0;
featureIndex < featureCollection.Features.Count;
featureIndex++)
{
// get json feature
var jsonFeature = featureCollection.Features[featureIndex];
Geometry geom = null;
// get geometry type to create appropriate geometry
switch (jsonFeature.Geometry.Type)
{
case GeoJSONObjectType.Point:
break;
case GeoJSONObjectType.MultiPoint:
break;
case GeoJSONObjectType.LineString:
break;
case GeoJSONObjectType.MultiLineString:
break;
case GeoJSONObjectType.Polygon:
{
var polygon = jsonFeature.Geometry as GeoJSON.Net.Geometry.Polygon;
var coordinates = new List <Point3D>();
foreach (var ring in polygon.Coordinates)
{
if (ring.IsLinearRing())
{
foreach (var coordinate in ring.Coordinates)
{
var location = coordinate as GeographicPosition;
if (location == null)
{
continue;
}
coordinates.Add(new Point3D(location.Longitude,
location.Latitude,
location.Altitude.HasValue ? location.Altitude.Value : 0 ));
}
}
}
geom = new Polygon(new LinearRing(new CoordinateSequence(coordinates.ToArray())),
null);
}
break;
case GeoJSONObjectType.MultiPolygon:
break;
case GeoJSONObjectType.GeometryCollection:
break;
case GeoJSONObjectType.Feature:
break;
case GeoJSONObjectType.FeatureCollection:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
//Steps to Converting GeoJSON response to FeatureCollection
//1. Add NetTopologySuite.IO.GeoJson package from Nuget Package Manager.
//2. Write Following Code Snap:
string Filepath = "Your filepath here";
var josnData = File.ReadAllText(Filepath);
var reader = new NetTopologySuite.IO.GeoJsonReader();
var featureCollection =
reader.Read<GeoJSON.Net.Feature.FeatureCollection>(josnData);
//in my case i did it like this
for (int fIndex = 0; fIndex < featureCollection.Features.Count; fIndex++)
{
var AreaDetails =
featureCollection.Features[fIndex].Properties;
for (int AIndex = 0; AIndex < AreaDetails.Count;
AIndex++)
{
var element = AreaDetails.ElementAt(AIndex);
var Key = element.Key;
var Value = element.Value;
if (Key == "GML_ID")
{
areaDetails.StateCode = Value.ToString();
}
else if (Key == "STNAME")
{
areaDetails.State = Value.ToString();
}
else if (Key == "DISTFULL")
{
areaDetails.DistrictCode = Value.ToString();
}
else if (Key == "DTNAME")
{
areaDetails.District = Value.ToString();
}
else if (Key == "IPCODE")
{
areaDetails.TalukaCode = Value.ToString();
}
else if (Key == "IPNAME")
{
areaDetails.Taluka = Value.ToString();
}
else if (Key == "VLGCD2001")
{
areaDetails.AreaCode = Value.ToString();
}
else if (Key == "VILLNAME")
{
areaDetails.AreaName = Value.ToString();
}
}
var AreaCoords = featureCollection.Features[fIndex].Geometry;
var Type = AreaCoords.Type;
LocationDetails locationDetails = new LocationDetails();
if (Type == GeoJSONObjectType.Polygon)
{
var polygon = AreaCoords as GeoJSON.Net.Geometry.Polygon;
var polygonCoords = polygon.Coordinates[0].Coordinates;
for (int AIndex = 0; AIndex < polygonCoords.Count; AIndex++)
{
locationDetails.lat = Convert.ToDecimal(polygonCoords[AIndex].Latitude);
locationDetails.lng = Convert.ToDecimal(polygonCoords[AIndex].Longitude);
locationDetailsList.Add(locationDetails);
}
}

Control validation against XmlSchemaSimpleTypeRestriction.Facets

I have a a desktop application with a System.Windows.Form containing some TextBox controls. I need to validate the control values against restrictions of an xml schema.
For each TextBox I can retrieve the relevant XmlSchemaSimpleTypeRestriction from its type and then use a method as follows to validate its value:
public static bool Validate(XmlSchemaSimpleTypeRestriction restriction, string value)
{
bool isENum = false;
bool isValidEnum = false;
foreach (var item in restriction.Facets)
{
XmlSchemaLengthFacet lengthFacet = item as XmlSchemaLengthFacet;
if (lengthFacet != null)
{
int length = Int32.Parse(lengthFacet.Value);
if (!(value.Length == length))
return false;
}
XmlSchemaMinLengthFacet minLenghtFacet = item as XmlSchemaMinLengthFacet;
if (minLenghtFacet != null)
{
int length = Int32.Parse(minLenghtFacet.Value);
if (!(value.Length >= length))
return false;
}
XmlSchemaMaxLengthFacet maxLenghtFacet = item as XmlSchemaMaxLengthFacet;
if (maxLenghtFacet != null)
{
int length = Int32.Parse(maxLenghtFacet.Value);
if (!(value.Length <= length))
return false;
}
XmlSchemaPatternFacet patternFacet = item as XmlSchemaPatternFacet;
if (patternFacet != null)
{
Regex re = new Regex(patternFacet.Value);
if (!re.IsMatch(value))
return false;
}
XmlSchemaEnumerationFacet enumFacet = item as XmlSchemaEnumerationFacet;
if (patternFacet != null)
{
isENum = true;
if (StringComparer.InvariantCultureIgnoreCase.Compare(value, enumFacet.Value) == 0)
isValidEnum = true;
}
if (isENum && (!isValidEnum))
return false;
return true;
}
I am going to use this method in the Validating event of the controls. Is there any simpler way of doing this?
Ok, it's a little more complicated than I initially thought. Basically, you need create an XmlSchema that expects a single element with the provided restriction. Then you create an XML element with the provided value and validate it against the schema using an XmlReader:
public static bool Validate(XmlSchemaSimpleTypeRestriction restriction, string value)
{
var schema = new XmlSchema();
schema.Items.Add(new XmlSchemaElement
{
Name = "value",
SchemaType = new XmlSchemaSimpleType { Content = restriction }
});
var schemaSet = new XmlSchemaSet();
schemaSet.Add(schema);
var readerSettings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings,
Schemas = schemaSet
};
string xml = new XElement("value", value).ToString();
try
{
var reader = XmlReader.Create(new StringReader(xml), readerSettings);
while (reader.Read()) ;
return true;
}
catch (XmlSchemaValidationException)
{
return false;
}
}
I tested it with this code:
static void Main(string[] args)
{
var restriction = new XmlSchemaSimpleTypeRestriction { BaseTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema") };
restriction.Facets.Add(new XmlSchemaMinLengthFacet { Value = "3" });
Console.WriteLine(Validate(restriction, "str"));
}

How to judge the node of json exists

I am using Newtonsoft.Json to Deserialize json string to Object, but I can't judge if the node is null or not. eg. jo["data"]["prevtime"], sometimes json has the node of ["prevtime"], sometimes doesn't have ["prevtime"]. If ["prevtime"] is null, it will report an error.
var jo = JObject.Parse(content);
if (jo["data"].ToString() == "")
return new StatusCollection();
var jInfo = jo["data"]["info"];
StatusCollection list = new StatusCollection();
Status status = null;
if (jInfo != null)
{
foreach (var j in jInfo.Children())
{
if (jo["data"]["prevtime"] != null)
{
status.Nexttime = jo["data"]["nexttime"].ToString();
status.Prevtime = jo["data"]["prevtime"].ToString();
}
status = j.ToObject<Status>();
if (!string.IsNullOrEmpty(status.Head))
{
status.Head += "/50";
}
if (!string.IsNullOrEmpty(status.From))
{
status.From = "来自" + status.From;
}
list.Add(status);
}
}
In the current version, it would be like :
if (jo["data"].Select***Token***("prevtime") != null)
{
status.Prevtime = jo["data"].Value<string>("prevtime");
status.Nexttime = jo["data"].Value<string>("nexttime");
}
Try to select the token you want, and there is a property to get the token value
if (jo["data"].Select("prevtime") != null)
{
status.Prevtime = jo["data"].Value<string>("prevtime");
status.Nexttime = jo["data"].Value<string>("nexttime");
}
JSON.NET Documentation:
Link 1
Link 2

How to get the contents of a HTML element using HtmlAgilityPack in C#?

I want to get the contents of an ordered list from a HTML page using HTMLAgilityPack in C#, i have tried the following code but, this is not working can anyone help, i want to pass html text and get the contents of the first ordered list found in the html
private bool isOrderedList(HtmlNode node)
{
if (node.NodeType == HtmlNodeType.Element)
{
if (node.Name.ToLower() == "ol")
return true;
else
return false;
}
else
return false;
}
public string GetOlList(string htmlText)
{
string s="";
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(htmlText);
HtmlNode nd = doc.DocumentNode;
foreach (HtmlNode node in nd.ChildNodes)
{
if (isOrderedList(node))
{
s = node.WriteContentTo();
break;
}
else if (node.HasChildNodes)
{
string sx= GetOlList(node.WriteTo());
if (sx != "")
{
s = sx;
break;
}
}
}
return s;
}
The following code worked for me
public static string GetComments(string html)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string s = "";
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//ol"))
{
s += node.OuterHtml;
}
return s;
}
How about:
var el = (HtmlElement)doc.DocumentNode
.SelectSingleNode("//ol");
if(el!=null)
{
string s = el.OuterHtml;
}
(untested, from memory)

Categories