XMLPATH has an invalid token - c#

I want to extract all the ndoes whose Date element has today's DateTime except seconds which is 10 seconds less than datetime.now.
Here is the code.
C#
DateTime total_seconds = Convert.ToDateTime(DateTime.Now.AddSeconds(-10));
string st = "_127.0.0.1";
//string v = "1";
XPathNodeIterator itr = nav.Select("pings/ping" + st + "[DATE<" + total_seconds + "]/DATE");
XML
<pings>
<ping_127.0.0.1>
<IP>127.0.0.1</IP>
<RTT>0</RTT>
<DATE>13-09-2015 16:47:09</DATE>
</ping_127.0.0.1>
<ping_127.0.0.1>
<IP>127.0.0.1</IP>
<RTT>1</RTT>
<DATE>13-09-2015 16:47:10</DATE>
</ping_127.0.0.1>
<ping_127.0.0.1>
<IP>127.0.0.1</IP>
<RTT>2</RTT>
<DATE>13-09-2015 16:47:11</DATE>
</ping_127.0.0.1>
<ping_127.0.0.1>
<IP>127.0.0.1</IP>
<RTT>1</RTT>
<DATE>13-09-2015 16:47:12</DATE>
</ping_127.0.0.1>
</pings>
This is the error

XPathNodeIterator itr = nav.Select("pings/ping" + st + "[DATE<" + total_seconds + "]/DATE");
While you haven't pasted in the error, from the title it says: "Invalid token". Your code suggests a string as XPath statement something along those lines:
pings/ping_127.0.0.1[DATE<37712828]/DATE
But since the total_seconds variable is of type DateTime, I assume it is a string something like "2015-10-09...13:22:56.584". Which is most likely the cause of your invalid token.
If not, can you put a breakpoint in your code and paste the resulting XPath?
Note: what you are trying to achieve is not (quite) possible, you cannot compare a date/time value with greater-than operators in XPath 1.0. It requires at least XPath 2.0 to do that. A workaround is, unfortunately, not trivial.

Related

Can I shorten this code with a loop in C#?

I have this code written in C# but looks kind of "bad" and I would like to shorten it somehow and keep it clean and simple.
All this code works pretty fine but I want to know if there's any other way I can achieve the same thing.
EDIT: I forgot to mention that the firstLine has a bad date format attached with it, so it is like this: "This_is_my_first_line_20220126". So I split the string and then only join it with the corrected date. The problem is that I can never know how long the new string would be and I don't want to handle the code like this and go up to 100 parts.
Here's my code:
string correctDate = "26012022";
string[] lines = File.ReadAllLines("text.txt");
string firstLine = lines.FirstOrDefault();
//note: firstLine looks like this: This_is_my_first_line_20220126
string[] sub = firstLine.Split('_');
string name="";
if(sub.Length==2)
name = sub[0]+"_"+sub[1]+"_"+correctDate;
else if(sub.Length==3)
name = sub[0]+"_"+sub[1]+"_"+sub[2]+"_"correctDate;
...
else if(sub.Length==20)
name = sub[0]+"_"+ ... "_" + sub[19];
Now, my final name value should be "This_is_my_line_26012022" but I want it to depend on the length of the given string. So far I know that the maximum length would go up to 20 but I don't want my code to look like this. Can I shorten it somehow?
you can find the LastIndexOf the underscore and drop the date by using Substring:
string firstLine = "This_is_my_first_line_20220126";
string correctDate = "26012022";
string correctString = firstLine.Substring(0, firstLine.LastIndexOf("_") + 1) + correctDate;
Still a little perplexed with the split aproach, but this a way to join back all elements
string name = string.Join("_", sub.Take(sub.Length - 1).Append(correctDate));
Or use the substring method (and no need of all that split & join)
name = firstLine.Substring(0, firstLine.LastIndexOf("_") +1) + correctDate;
I forgot to mention that firstLine has a bad date format like "This_is_my_Line_20220125"
If you want to correct just the first line:
string correctDate = "26012022";
string[] lines = File.ReadAllLines("text.txt");
lines[0] = lines[0][..^8] + correctDate;
[..^8] uses C# 9's "indices and ranges" feature, that allows for a more compact way of taking a substring. It means "from the start of the string, up to the index 8 back from the end of the string".
If you get a wiggly line and possibly a messages like "... is not available in C# version X" you can use the older syntax, which would be more like lines[0] = lines[0].Remove(lines[0].Length - 8) + correctDate;
If you want to correct all lines:
string correctDate = "26012022";
string[] lines = File.ReadAllLines("text.txt");
for(int x = 0; x < lines.Length; x++)
lines[x] = lines[x][..^8] + correctDate;
If the incorrect date isn't always 8 characters long, you can use LastIndexOf('_') to locate the last _, and snip it to that point

Get substring in between two other strings?

I am trying to get a string in between two sub strings, but I am running into an issue.
I am trying to use Selenium to automate a web test, and extract the profile ID from the javascript in the page source. I am running into an ArgumentOutOfRangeException?
It doesn't matter with I'm searching for the correct or wrong values and passing them to GetInbetween, it throws this exception. I cannot see anything wrong with my code, so here I am.
Code:
var source = GetSource();
var username = "username1";
Console.WriteLine("Here: " + source.GetInbetween("window.__additionalDataLoaded('/" + username + "/',{\"logging_page_id\":\"", "\","));
Source (truncated for readability):
window.__additionalDataLoaded('/username1/',{"logging_page_id":"profilePage_10216","logging_page_username": "username1"})
Exception:
ArgumentOutOfRangeException
Length cannot be less than zero. (Parameter 'length')
It throws the exception in this method
public static string GetInbetween(this string s, string start, string end)
{
return s[(s.IndexOf(start) + start.Length)..s.IndexOf(end)];
}
LinqPad test:
void Main()
{
var source = "window.__additionalDataLoaded('/username1/',{\"logging_page_id\":\"profilePage_10216\",\"logging_page_username\":\"username1\"})";
var username = "username1";
Console.WriteLine(source.IndexOf("window.__additionalDataLoaded('/" + username + "/',{\"logging_page_id\":\""));
Console.WriteLine(source.IndexOf("\","));
Console.WriteLine($"[{source}]");
Console.WriteLine($"[{"window.__additionalDataLoaded('/" + username + "/',{\"logging_page_id\":\""}]");
Console.WriteLine("Here: " + source.GetInbetween("window.__additionalDataLoaded('/" + username + "/',{\"logging_page_id\":\"", "\"."));
}
You might get this error if end exists in s before start. So try using s.LastIndexOf(end).
It says 'Length cannot be less than zero.' which means IndexOf is returning -1, which it does if the substring is not found in the search string... So you are looking for a substring which doesn't exist in the string. Make sure you have case-sensitivity correct, or use an IndexOf overload which ignores case.
Edit -- Your GetSource() method must not be returning the string you think it is returning... See, works fine explicitly searching that string:
Passing a start index to IndexOf(end) like this seems to fix it.
return s[(s.IndexOf(start) + start.Length)..s.IndexOf(end, s.IndexOf(start))];
The final method looks like this:
public static string GetInbetween(this string s, string start, string end)
{
return s[(s.IndexOf(start) + start.Length)..s.IndexOf(end, s.IndexOf(start))];
}

C# building a string for JSON using variables

I'm relatively new to C# and trying to deserialize a string from JSON for this value; ["format"]["tags"]["ENCODER"]
// Manually building the string works fine
string test = (dict["format"]["tags"]["ENCODER"]);
string found_value = "";
const char quote = '\u0022';
string encoder = "[" + quote + "format" + quote + "][" + quote + "tags" + quote + "][" + quote + "ENCODER" + quote + "]";
// Just as a test
encoder = encoder.Replace("\u005c\u0022", "\u0022");
// This Fails
found_value = (dict[encoder]);
It throws an exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in mscorlib.dll but was not handled in user code
Additional information: The given key was not present in the dictionary.
So I'm sure it's the way I'm passing the encoder string. Probably something really simple but I've spent hours trying various things and become blind to it now.
Thanks in advance
Basically, C# isn't a scripting language, but is a compiled language. This means that there is no equivalent of a javascript eval() function, and strings don't perform the same as the equivalent code string. So the second lookup, you're trying to do this:
dict["[\"format\"][\"tags\"][\"eval\"]")
And it is rightly complaining that your first dictionary there doesn't have a key of the name
"[\"format\"][\"tags\"][\"eval\"]"
Why are you trying to do this in the second way, when the first one works?

string.replace() not working with xml string

I have read all similar questions and acted accordingly. But still can't figure out what's wrong with my code.
This is my code, super simple. (I know this isn't valid XML. It's just for the example).
string replacement = "TimeSheetsReplaced";
string word = "TimeSheets";
string result = "<?xml version=\"1.0\" encoding=\"utf-16\"?><DisplayName>Timesheets</DisplayName>";
result = result.Replace("<DisplayName>" + word + "</DisplayName>", "<DisplayName>" + replacement + "</DisplayName>");
The result string remains unplaced. What am I doing wrong??
TimeSheets != Timesheets
Casing does not match
It's because your string contains Timesheets, but you're lokoing for TimeSheets (with a capital S).
In your word TimeSheets has big S, in string small s

Xpath error has an Invalid Token

I have the following C# code:
var selectNode = xmlDoc.SelectSingleNode("//CodeType[#name='" + codetype +
"']/Section[#title='" + section + "']/Code[#code='" + code + "' and
#description='" + codedesc + "']") as XmlElement;
when I run my code it raises the error saying "the above statement has an invalid token"
These are the values for the above statement.
codeType=cbc
section="Mental"
codedesc="Injection, enzyme (eg, collagenase), palmar fascial cord (ie,
Dupuytren's contracture"
Notice the apostrophe (') in codedesc?
You need to escape it somehow. The XPath interpreter considers it as a string delimiter and doesn't know how to treat the other apostrophe after it.
One way you can do that is by enclosing your string in double quotes instead of apostrophes.
Your code could therefore become:
var selectNode = xmlDoc.SelectSingleNode(
"//CodeType[#name='" + codetype + "']" +
"/Section[#title='" + section + "']" +
"/Code[#code=\"" + code + "' and #description='" + codedesc + "\"]")
as XmlElement;
(note that on the fourth line, the apostrophes(') became double quotes(\"))
While this approach works for the data you presented, you are still not 100% safe: other records could contain double quotes themselves. If that happens, we'll need to think of something for that case as well.
You can get selected node based on index , if any special characters in the xml schema. So , here looks below implementation for delete selected index node from xml schema.
XML SelectSingleNode Delete Operation
var schemaDocument = new XmlDocument();
schemaDocument.LoadXml(codesXML);
var xmlNameSpaceManager = new XmlNamespaceManager(schemaDocument.NameTable);
if (schemaDocument.DocumentElement != null)
xmlNameSpaceManager.AddNamespace("x", schemaDocument.DocumentElement.NamespaceURI);
var codesNode = schemaDocument.SelectSingleNode(#"/x:integration-engine-codes/x:code-categories/x:code-category/x:codes", xmlNameSpaceManager);
var codeNode = codesNode.ChildNodes.Item(Convert.ToInt32(index) - 1);
if (codeNode == null || codeNode.ParentNode == null)
{
throw new Exception("Invalid node found");
}
codesNode.RemoveChild(codeNode);
return schemaDocument.OuterXml;
Duplicate the single quote, so that it reads "Dupuytren''s contracture"
This way you can escape the single quote in the xpath expression.

Categories

Resources