Cannot get data from XPath - c#

I am trying to get some data from a web page with HtmlAgilityPack which gets some variables and gives some results.
I want to retrieve 3 data fields from this webpage and so far I can only get the 2 of them.
My code so far
struct Result
{
public string Description;
public string thirdCountryDuty;
public string tarifPreference;
}
private Result LoadWebPage(string url, string taric)
{
//This is the webpage which contains all three datas that I want. I just write it here as
url for testing
url = "https://ec.europa.eu/taxation_customs/dds2/taric/measures.jsp?Lang=en&SimDate=20200503&Area=SG&MeasType=&StartPub=&EndPub=&MeasText=&GoodsText=&op=&Taric=6213900010&search_text=goods&textSearch=&LangDescr=el&OrderNum=&Regulation=&measStartDat=&measEndDat=%22;"
var result = new Result();
taric = "6213900010";//This is a variable. I give it here for testing purposes
txtEditCountry.Text = "SG";//This is a variable. I give it here for testing purposes
try
{
var web2 = new HtmlWeb();
var doc2 = web2.LoadFromBrowser(url, html =>
{
// WAIT until the dynamic text is set
return !html.Contains("<div id=\"" + taric.ToString() + "\"></div>");
});
//t1 is the data that I cannot get
var t1 = doc2.DocumentNode.SelectSingleNode("//span[contains(text(),'" + txtEditCountry.Text + "')] and .//span[contains(.,'duty_rate')]]").InnerText;
//This is working
var t2 = doc2.DocumentNode.SelectSingleNode("//*[contains(#id,'"+ taric + "')]/table/tbody/tr/td[2]/table/tbody/tr/td[2]").InnerText;
//This is working
var t3 = doc2.DocumentNode.SelectSingleNode("//span[contains(#class,'duty_rate')]").InnerText;
Console.WriteLine("Text 1: " + t1);
Console.WriteLine("Text 2: " + t2);
Console.WriteLine("Text 3: " + t3);
result = new Result
{
Description = t2,
thirdCountryDuty = t3,
tarifPreference = t1
};
return result;
}
catch (Exception ex)
{
result.Description= null;
result.thirdCountryDuty = null;
result.tarifPreference = null;
MessageBox.Show("Check your data and try again \n" + ex.ToString());
return result;
}
}
The data that I cannot get is t1 as I wrote in the code. This field is visible when I put a specific country in url "&Area=country code". If I put another country it will give me another number or 0%. If I don't put anything it will give me a list with all countries.
If I use this as Xpath
var t1 = doc2.DocumentNode.SelectSingleNode("//span[contains(text(),'" + txtEditXora.Text + "')]").InnerText;
It returns the country correct for example
Singapore (SG)
I want the tarif Preference percentage for this country
This is the first time that I use XPath and I am still learning but I wan't this for my project.

You can try this. I don't have time to check if it would work with other countries.
doc2.DocumentNode.SelectNodes("//div[#id='" + taric + "']//td[#name='measure_description_search']//td")[4].InnerText
Or this:
doc2.DocumentNode.SelectNodes("//div[#id='" + taric + "']//span[#class='duty_rate']")[1].InnerText

This should work
//text()[contains(.,"preference")]/../../td[2]

Related

C# - Change Streams in MongoDB with $match

I'm trying to narrow down the Change streams in MongoDB to a specific document matching on the document's _id as I have many documents in one collection. Anyone know how to do this in C#? Here's the latest that I've tried to no avail:
{
var userID = "someIdHere";
var match = new BsonDocument
{
{
"$match",
new BsonDocument
{
{"_id", userID}
}
}
};
var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<Class>>().Match(match);
var options = new ChangeStreamOptions { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup };
var cursor = collection.Watch(pipeline, options).ToEnumerable();
foreach (var change in cursor)
{
Debug.WriteLine(change.FullDocument.ToJson());
Debug.WriteLine(change.ResumeToken + " " + change.OperationType);
}
}
If I change the cursor to what you see below, it works but it returns the world and returns the change stream when there's activity on any of the _id's present in the document. That's not what I'm going for.
var cursor = collection.Watch().ToEnumerable();
After searching near and far, I was able to piece together bits and pieces of information from other issues I found online and came up with the solution below. It works like a charm!
Not only was I able to filter Change Stream so that it only recognizes updates but I was able to narrow down the stream to a SPECIFIC document _id AND made it even more granular finding a specific change to a field called LastLogin for that _id. This is what I desired as the default Change stream returned any update that happened on the collection.
I hope this helps someone that come across the same issue I did. Cheers.
{
var db = client.GetDatabase(dbName);
var collectionDoc = db.GetCollection<BsonDocument>(collectionName);
var id = "someID";
//Get the whole document instead of just the changed portion
var options = new ChangeStreamOptions
{
FullDocument = ChangeStreamFullDocumentOption.UpdateLookup
};
//The operationType of update, where the document id in collection is current one and the updated field
//is last login.
var filter = "{ $and: [ { operationType: 'update' }, " +
"{ 'fullDocument._id' : '" + id + "'}" +
"{ 'updateDescription.updatedFields.LastLogin': { $exists: true } } ] }";
var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<BsonDocument>>().Match(filter);
var changeStream = collectionDoc.Watch(pipeline, options).ToEnumerable().GetEnumerator();
try
{
while (changeStream.MoveNext())
{
var next = changeStream.Current;
Debug.WriteLine("PRINT-OUT:" + next.ToJson());
}
}
catch (Exception ex)
{
Debug.WriteLine("PRINT-OUT: " + ex);
}
finally
{
changeStream.Dispose();
}
}

Making several similar specific methods generic

I have a method like so...
static async Task GetLeads(ForceClient client)
{
Console.WriteLine("Get Leads");
var accts = new List<Lead>();
var results = await client.QueryAsync<Lead>(Lead._select);
var totalSize = results.TotalSize;
Console.WriteLine("Queried " + totalSize + " leads.");
accts.AddRange(results.Records);
Console.WriteLine("Added " + results.Records.Count + " leads...");
var nextRecordsUrl = results.NextRecordsUrl;
if (!string.IsNullOrEmpty(nextRecordsUrl))
{
Console.WriteLine("Found more records...");
while (true)
{
var continuationResults = await client.QueryContinuationAsync<Lead>(nextRecordsUrl);
Console.WriteLine("Queried an additional " + continuationResults.Records.Count + " leads.");
accts.AddRange(continuationResults.Records);
if (string.IsNullOrEmpty(continuationResults.NextRecordsUrl)) break;
nextRecordsUrl = continuationResults.NextRecordsUrl;
}
}
Upsert(accts, Lead.target);
}
I have another method like so..
static async Task GetSupplierProducts(ForceClient client)
{
Console.WriteLine("Get SupplierProduct");
var accts = new List<SupplierProduct>();
var results = await client.QueryAsync<SupplierProduct>(SupplierProduct._select);
var totalSize = results.TotalSize;
Console.WriteLine("Queried " + totalSize + " SupplierProduct.");
accts.AddRange(results.Records);
Console.WriteLine("Added " + results.Records.Count + " SupplierProduct...");
var nextRecordsUrl = results.NextRecordsUrl;
if (!string.IsNullOrEmpty(nextRecordsUrl))
{
Console.WriteLine("Found more records...");
while (true)
{
var continuationResults = await client.QueryContinuationAsync<SupplierProduct>(nextRecordsUrl);
Console.WriteLine("Queried an additional " + continuationResults.Records.Count + " SupplierProduct.");
accts.AddRange(continuationResults.Records);
if (string.IsNullOrEmpty(continuationResults.NextRecordsUrl)) break;
nextRecordsUrl = continuationResults.NextRecordsUrl;
}
}
Upsert(accts, SupplierProduct.target);
}
How can I make a method that abstracts this behavior generically?
The types Lead and SupplierProduct must somehow be related in the sense that they either implement the same interface or inherit from the same base class to make this work. Apparently the similarities are _select which apparently is a static member which cannot be included in an interface. Furthermore, the generation of human-readable strings would have to be refactored into the types.
If Base would be hypothetical base class, the signature of the generic function would have to be as follows.
static async Task Get<T>(ForceClient client) where T : Base
Assuming both Lead and SupplierProduct inherits the same Parent:
static async Task GetMyInstance<T>(ForceClient client) where T : Parent
{
Console.WriteLine("Get " + T.GetType().Name);
var accts = new List<T>();
var results = await client.QueryAsync<T>(T._select);
var totalSize = results.TotalSize;
Console.WriteLine("Queried " + totalSize + " " + T.GetType().Name +".");
accts.AddRange(results.Records);
Console.WriteLine("Added " + results.Records.Count + T.GetType().Name + "...");
var nextRecordsUrl = results.NextRecordsUrl;
if (!string.IsNullOrEmpty(nextRecordsUrl))
{
Console.WriteLine("Found more records...");
while (true)
{
var continuationResults = await client.QueryContinuationAsync<T>(nextRecordsUrl);
Console.WriteLine("Queried an additional " + continuationResults.Records.Count + " " + T.GetType().Name + ".");
accts.AddRange(continuationResults.Records);
if (string.IsNullOrEmpty(continuationResults.NextRecordsUrl)) break;
nextRecordsUrl = continuationResults.NextRecordsUrl;
}
}
Upsert(accts, T.target);
}
Please note that Parent should contain _select and target for this to work
And you call it like this:
var foo = GetMyInstance<Lead>(forceClient);
or
var foo = GetMyInstance<SupplierProduct>(forceClient);
This likely won't suffice fully, but when I want to make multiple partial-similar methods accessible through a single function, I tend to pass target-strings and use a repeating switch-statement on them.
This way we can also run multiple actions after each other by supplying an array of targets.
Note; this code isn't debugged or anything, I just wanted to point you towards how switch-statements might be of some use to you. It wasn't possible for me to give a more comprehensive answer because I can't fully understand the intent of your code.
static async Task GetRecordsFor(ForceClient client, string[] targets )
{
foreach (string target in targets){
switch ( target )
{
case 'leads':
Console.WriteLine("Get Leads");
var accts = new List<Lead>();
// more specific code for fetching leads
break;
case 'suppliers':
Console.WriteLine("Get SupplierProduct");
var accts = new List<SupplierProduct>();
// more specific code for fetching suppliers
break;
}
// Actions you want to perform on each of these.
accts.AddRange(continuationResults.Records);
}
}

GnU GPL v2 DHTMLX ASP.net C# - How to read data from data base (JSON) returned by a class

I read that I can do something like this
scheduler.parse([
{ start_date:"2013-05-13 6:00", end_date:"2009-05-13 8:00", text:"Event 1"},
{ start_date:"2013-06-09 6:00", end_date:"2009-06-09 8:00", text:"Event 2"}
],"json");
on http://docs.dhtmlx.com/scheduler/api__scheduler_parse.html
but I dont want to manually place all data, I want it to read data from my database
so what I did is that I have this method on Data.ashx
public string getJson(int ID)
{
XXXContext db = new XXXContext();
var YYYY = db.Y.Where(p => p.YYYID == ID).Include(p => p.ZZZZ).ToList();
List<CalendarEvent> cEvent = new List<CalendarEvent>();
foreach (var evnt in YYYYY)
{
cEvent.Add(new CalendarEvent() { id = evnt.AAAAID, text = evnt.PPPPP.FirstName.ToString() + " " + evnt.PPPPP.MiddleName.ToString() + " " + evnt.PPPPP.LastName.ToString() + "<br />" +
evnt.Reason.ToString() + "<br />" + evnt.Details.ToString(), start_date = evnt.XXXXXDateTime??DateTime.Now, end_date = evnt.XXXXXDateTime??DateTime.Now });
}
IEnumerable<CalendarEvent> toIEnum = cEvent;
string json = new JavaScriptSerializer().Serialize(toIEnum);
return json;
}
This returns a JSON formatted output
but i dont know what to do next<
this is what i got on my html file, which I called using IFrame on my aspx class
<script type="text/javascript" charset="utf-8">
function init() {
scheduler.config.multi_day = true;
scheduler.config.xml_date="%Y-%m-%d %H:%i";
scheduler.init('scheduler_here',new Date(2015,0,10),"week");
scheduler.load("../../Data.ashx");
}
You need to specify data format in arguments of scheduler.load, otherwise it would expect xml by default:
scheduler.load("../../Data.ashx", "json");
Also note that the client side will expect start_date/end_date dates to be serialized in the format specified in scheduler.config.xml_date config ("%Y-%m-%d %H:%i" according to your code) while JavaScriptSerializer will stringify DateTime into something following:
"start_date": "/Date(1355496152000)/"
there are a couple of possible workarounds, for example, you can override a method that parses dates and parse them manually:
scheduler.templates.xml_date = function (dateString) {
var timestamp = dateString.substring(6, dateString.length - 2);
return new Date(timestamp * 1);
};
scheduler.load("../../Data.ashx", "json");

C# Webservice stucks. Need to override published file to restart

Please help me, I'm facing a fatal problem here. If someone could fix this, I swear I will treat u to a huge drink whenever u step into my country (Vietnam). Ok here's the problem: I'm coding a webservice for multi connection simultaneously from tablet (around 100 clients). It ran well but recently whenever high traffic occurs, my webservice seems to stuck somehow and I need to copy - override the published file of webservice in order for it to run again (restart website in IIS is no use) ...
This is my w/s code for handling the data:
public string Info_Handling(string id, string name, string strDetails)
{
string checkExist = "";
string str = "";
string str2 = "";
MLL_Customer _customerClient = new MLL_Customer();
MLL_CustomerCategory _categoryClient = new MLL_CustomerCategory();
MLL_Product _productClient = new MLL_Product();
MLL_SampleProduct _sampleClient = new MLL_SampleProduct();
if (_customerClient.CheckExistCustomer(id, name.ToUpper(), 2) == 1) // SID & NAME
{
checkExist = "EXIST";
}
using (SqlConnection connection = new SqlConnection(ConfigurationSettings.AppSettings["Main.ConnectionString"]))
{
connection.Open();
SqlTransaction trans = connection.BeginTransaction("XXX");
try
{
// ID Example: 11 means VIP - 12 means Normal - 13 means ples... jkg
// First - Insert Customer
string strCustomerCategory = _categoryClient.SelectCategoryByID(id).ToString();
if (!checkExist.Equals("EXIST"))
{
Customer businessObject = new Customer();
businessObject.ID = sid;
businessObject.Name = name.ToUpper();
businessObject.CategoryID = strCustomerCategory;
str = "" + _customerClient.Insert(businessObject, connection, trans);
}
// Second Insert Product spliting from a string Ex: "TV&Laptop&CD"
string[] productDetails = strDetails.Split(new char[] { '&' });
object obj3;
SampleProduct objSample;
Product objProduct;
for (int j = 0; j < productDetails.Length; j++)
{
if (_productClient.CheckExist(id, productDetails[j])) == null) // Check if customer already owns this product
{
// Get the properties of sample product.
objSample = _sampleClient.SelectSampleProduct(productDetails[j]);
objProduct = new Product();
objProduct.SID = sid;
objProduct.Testcode = objSample.TestCode;
objProduct.Category = objSample.Category;
objProduct.Unit = objSample.Unit;
objProduct.Price = objSample.Price;
if (_productClient.Insert(objProduct, connection, trans) != 0)
{
str2 = str2 + "&" + objProduct.Testcode;
// return the code of product in order to see which product has been inserted successfully
}
}
}
trans.Commit();
SqlConnection.ClearAllPools();
}
catch (Exception exception)
{
str = "0";
str2 = exception.Message + exception.Source;
try
{
trans.Rollback();
}
catch (Exception)
{
}
}
}
if (!str2.Equals(""))
{
return (str + "&" + id + str2);
}
return ("0&" + sid + str);
}
I modified the code but this is basically how i roll. Could anyone plz tell me some solution. Deeply thank u.
1 more thing about ClearAllPools() method: I know how it works but I dont even know why I need it. Without this, my data will be messed up terrible. CategoryID of one customer will be assigned for another customer sometimes. ???? How could it happened ?? HELP

Parse input and build a Dictionary/HashMap while parsing

I am not sure if the title makes it clear what I want to do.
My input for my parser contains debug information about C source files. Some of the input looks e.g. like this:
L:C$main.c$41$1$10:C0C5
Which basically means that line 10 in the source file main.c corresponds with the memory address C0C5.
Here is an example what my AST looks like:
Which represents the input:
M:main
L:C$main.c$29$1$0:C09C
L:C$main.c$30$1$10:C0A2
M:divide
L:C$divice.c$31$1$10:C5A9
What I want are two Hash-Maps such that I can access these information quickly at runtime. But how can I now build such Hash-Maps and is it possible to do that at parsetime?
This is how I would like to use my parser:
public CDBFileParser getFileParser(String cdbFilePath)
{
Stream stream = File.OpenRead(cdbFilePath);
ANTLRInputStream inputStream = new ANTLRInputStream(stream);
CDBFileLexer lexer = new CDBFileLexer(inputStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CDBFileParser parser = new CDBFileParser(tokens);
try
{
parser.TreeAdaptor = new CommonTreeAdaptor();
parser.parseCDBFile();
// All this works so far. Here comes the part I am looking for:
Modules[] modules = parser.getModules();
Dictionary<int, int> lineToAddress = modules[0].getLineToAddressMap();
Dictionary<int, int> addressToLine = modules[0].getAddressToLineMap();
int address = 0xC09C;
System.Out.WriteLine( "Address 0xC09C is at line " + addressToLine.get(address) + " in " + modules[0].getName() );
}
catch (Exception e)
{
printException(e);
}
return parser;
}
Expected Output:
Address 0xC09C is at line 29 in main
Can anybody help?
Best regards.
I was about to delete my question but maybe somebody else comes along to this post. I just made the transition to ANTLR4 and it really is much simpler (so far at least).
In ANTLR4 an interface (e.g. ICDBFileListener) is built for you which one can use to catch all information at parsetime:
namespace Parser
{
public class CDBFileParserListener : ICDBFileListener
{
public void ExitModule_name(CDBFileParser.Module_nameContext context)
{
Console.WriteLine("ModuleName: " + context.GetText());
// Add module to module-map and remember
// that current module is context.GetText()
}
public void ExitLine_number(CDBFileParser.Line_numberContext context)
{
Console.WriteLine("LineNumber: " + context.GetText());
// Remember line number
}
public void ExitMemory_address(CDBFileParser.Memory_addressContext context)
{
Console.WriteLine("MemoryAddress: " + context.GetText());
// Add linenumber <-> memoryaddress to maps
}
public Modules[] getModules()
{
return m_modules;
}
}
}
And this is how it can be used:
public CDBFileParser getFileParser(String cdbFilePath)
{
Stream stream = File.OpenRead(cdbFilePath);
AntlrInputStream inputStream = new AntlrInputStream(stream);
CDBFileLexer lexer = new CDBFileLexer(inputStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CDBFileParser parser = new CDBFileParser(tokens);
try
{
CDBFileParserListener listener = new CDBFileParserListener();
parser.AddParseListener(listener);
System.Diagnostics.Debug.WriteLine(parser.parseCDBFile().ToStringTree());
Dictionary<String, Module> modules = listener.Modules;
Module main;
modules.TryGetValue("main", out main);
long line = main.getLineFromAddress(0xC09C);
Console.WriteLine("0xC09C maps to " + line + " in main.c");
}
catch (Exception e)
{
printException(e);
}
return parser;
}

Categories

Resources