Can we search or filter " data-tag='to-do' " in onenote API ? If yes then how we can do this? - onenote

How can we use OneNote tags (like data-tag='to-do') with search or filter in OneNote API. I tried using provide operators but found no success.
I tried in this way --
$url = "https://www.onenote.com/api/v1.0/me/notes";
//$url .= "/pages?search=hello";
$url .= "/pages?filter=data-tag eq 'to-do'";
I want to search data-tag and then extract the data from OneNote pages which contains the data-tag='to-do'.
Any help is appreciated and thanks in advance.

You'll have to run through all your pages.
For each pages, you can retrieve its content with a GET call to https://www.onenote.com/api/v1.0/me/notes/pages/%s/content?includeIds=true
From there you get a string that you can parse.
I'll advise you to use jsoup.
With jsoup you can then write (assuming contentcontains your page's content):
Document doc = Jsoup.parse(content);
Elements todos=doc.select("[data-tag^=\"to-do\"]");
for(Element todo:todos) {
System.out.println(todo.ownText());
}

Sadly OneNote API doesn't support it yet, so I've written my custom parser which extracts notes with data-tags from page content. Here it is:
public class OneNoteParser
{
static public List<Note> ExtractTaggedNotes(string pageContent, string tag = "*")
{
List<Note> allNotes = new List<Note>();
string[] dataTagString = { "data-tag=\""};
string[] dirtyNotes = pageContent.Split(dataTagString, StringSplitOptions.RemoveEmptyEntries);
//First one in this array can be dropped as it doesn't contain todo
for (int i = 1; i < dirtyNotes.Length; i )
{
string curStr = dirtyNotes[i];
Note curNote = new Note();
// Firstly we need to extract all the tags from it (sample html: data-tag="to-do:completed,important" ....)
string allTags = curStr.Substring(0,curStr.IndexOf("\""));
curNote.Tags = new List<string>(allTags.Split(','));
// Now we have to jump to the next ">" symbol and start finding the text after it
curStr = curStr.Substring(curStr.IndexOf(">"));
int depth = 1;
bool addAllowed = false;
for (int j = 0; j < curStr.Length - 1; j )
{
// Finding next tag opener "<" symbol
if (curStr[j] == '<')
{
addAllowed = false;
// Checking if it is not "</" closer
if (curStr[j 1] == '/')
{
// Means this is a tag closer. Decreasing depth
depth--;
}
else
{
// Means this is an tag opener. Increasing depth
depth ;
}
}
else if (curStr[j] == '>')
{
addAllowed = true;
if (j > 0 && curStr[j - 1] == '/')
{
// Means this is a tag closer. Decreasing depth
depth--;
}
}
else
{
if (depth < 1)
{
// Found end of the tag. Saving index and exiting for loop
break;
}
if (addAllowed)
curNote.Text = curStr[j]; // Appending letter to string
}
}
// Filtering by tag and adding to final list
if (tag == "*" || curNote.Tags.Any(str => str.Contains(tag)))//curNote.Tags.Contains(tag, StringComparer.CurrentCultureIgnoreCase))
allNotes.Add(curNote);
}
return allNotes;
}
}
And here is the class Note
public class Note
{
public string Text;
public List<string> Tags;
public Note()
{
Tags = new List<string>();
}
}
To extract todo-s simply call this function:
OneNoteParser.ExtractTaggedNotes(pageContent, "to-do");
Also you can extract other tags like this:
OneNoteParser.ExtractTaggedNotes(pageContent, "important");
OneNoteParser.ExtractTaggedNotes(pageContent, "highlight");
//...

Related

How to get key values from Html in Flutter?

I have the following html string. how to decode this and get key values
<html>
<head></head>
<body>order_id=1289&tracking_id=111028965908&bank_ref_no=916831&order_status="
"Success&failure_message=&payment_mode=Credit Card&card_name=MasterCard&status_code=00&"
"status_message=Approved¤cy=AED&amount=140.0&billing_name=Gx&billing_address=Yd&billing_city=Ud&"
"billing_state=&billing_zip=Uf&billing_country=Andorra&billing_tel=4&billing_email=jasir6#gmail.com&"
"delivery_name=Gx&delivery_address=Yd&delivery_city=Ud&delivery_state=&delivery_zip=Uf&"
"delivery_country=Andorra&delivery_tel=4&merchant_param1=&merchant_param2=&merchant_param3="
"&merchant_param4=&merchant_param5=&vault=N&offer_type=null&offer_code=null&discount_value=0.0&"
"mer_amount=140.0&eci_value=05&card_holder_name=&bank_qsi_no=51000002968&bank_receipt_no=221315916831&"
"merchant_param6=5123450008
</body>
</html>
You can also use this code if you don't want to use plugin to get key-value data
Assign a keyValueMap globally if you want to use it anywhere else
String html = '<html><head></head><body>order_id=1289&tracking_id=111028965908&bank_ref_no=916831&order_status=Success&failure_message=&payment_mode=Credit Card&card_name=MasterCard&status_code=00&"status_message=Approved¤cy=AED&amount=140.0&billing_name=Gx&billing_address=Yd&billing_city=Ud&billing_state=&billing_zip=Uf&billing_country=Andorra&billing_tel=4&billing_email=jasir6#gmail.com&delivery_name=Gx&delivery_address=Yd&delivery_city=Ud&delivery_state=&delivery_zip=Uf&delivery_country=Andorra&delivery_tel=4&merchant_param1=&merchant_param2=&merchant_param3= &merchant_param4=&merchant_param5=&vault=N&offer_type=null&offer_code=null&discount_value=0.0&mer_amount=140.0&eci_value=05&card_holder_name=&bank_qsi_no=51000002968&bank_receipt_no=221315916831&merchant_param6=5123450008</body></html>';
onTap: () {
String temp;
const start = "<body>";
const end = "</body>";
Map<String, dynamic> keyValueMap = {};
if (html.contains(start)) {
final startIndex = html.indexOf(start);
final endIndex = html.indexOf(end, startIndex + start.length);
temp = html.substring(startIndex + start.length, endIndex);
List splitText = temp.split("&");
for (var element in splitText) {
element.runtimeType;
if (element.contains('=')) {
keyValueMap[element.split("=")[0] ?? ""] = element.split("=")[1] ?? "";
}
}
///You'll get all key value in [keyValueMap]
}
},
Use some Html decode plugins. Please go to pub.dev and search flutter_widget_from_html_core, flutter_widget_from_html, html_editor_enhanced,
so many plugins there in pub.dev.

How do I consume a JSon object that has no headers?

My C# MVC5 Razor page returns a Newtonsoft json link object to my controller (the "1" before \nEdit |" indicates that the checkbox is checked:
"{\"0\": [\"6146\",\"Kimball\",\"Jimmy\",\"General Funny Guy\",\"277\",\"Unite\",\"Jun 2019\",\"\",\"\",\"1\",\"\nEdit |\nDetails\n\n \n\"],\"1\": [\"6147\",\"Hawk\",\"Jack\",\"\",\"547\",\"Painters\",\"Jun 2019\",\"\",\"\",\"on\",\"\nEdit |\nDetails\n\n \n\"]}"
How do I parse this?
I am using a WebGrid to view and I want to allow the users to update only the lines they want (by checking the checkbox for that row), but it doesn't include an id for the 's in the dom. I figured out how to pull the values, but not the fieldname: "Last Name" , value: "Smith"... I only have the value and can't seem to parse it... one of my many failed attempts:
public ActoinResult AttMods(string gridData)
{
dynamic parsedArray = JsonConvert.DeserializeObject(gridData);
foreach (var item in parsedArray)
{
string[] itemvalue = item.Split(delimiterChars);
{
var id = itemvalue[0];
}
}
I finally sorted this one out..If there is a more dynamic answer, please share... I'll give it a few days before I accept my own (admittedly clugy) answer.
if(ModelState.IsValid)
{
try
{
Dictionary <string,string[]> log = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string[]>>(gridData);
foreach (KeyValuePair<string,string[]> keyValue in log)
{
if (keyValue.Value[9] == "1")//Update this row based on the checkbox being checked
{
var AttendeeID = keyValue.Value[0];
int intAttendeeID = 0;
if (int.TryParse(AttendeeID, out intAttendeeID))//Make sure the AttendeeID is valid
{
var LName = keyValue.Value[1];
var FName = keyValue.Value[2];
var Title = keyValue.Value[3];
var kOrgID = keyValue.Value[4];
var Org = keyValue.Value[5];
var City = keyValue.Value[7];
var State = keyValue.Value[8];
var LegalApproval = keyValue.Value[9];
tblAttendee att = db.tblAttendees.Find(Convert.ToInt32(AttendeeID));
att.FName = FName;
att.LName = LName;
att.Title = Title;
att.kOrgID = Convert.ToInt32(kOrgID);
att.Organization = Org;
att.City = City;
att.State = State;
att.LegalApprovedAtt = Convert.ToBoolean(LegalApproval);
}
}
}
db.SaveChanges();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
You can avoid assigning the var's and just populate the att object with the KeyValue.Value[n] value, but you get the idea.

How can I remove html tags for parsing the actual value and then put them back?

I am working on highlighting the search result in search difference app and I met some problems.
On the input we get some text inside <pre> tag, that already have some highlighted text using <span> tag.
<ng-container *ngIf="settings?.allowHtmlTransform">
<pre [innerHtml]="row?.value" ></pre>
</ng-container>
My job is to highlight current search result and this is the problem. The row.value I need to parse is something like <div class="NORMAL>Sample <span class="MISSING">Text</span></div>. There are decent amount of highlight classes (ex. MODIFIED, MISSING, EXTRA etc.)
I need to highlight search result (for example "a") but it starts looking inside tags and breaks formatting (for Highlight i use the same <span class="CURRENT">)</span>
The question is how can I parse value without these tags, but when I will return highlighted value they would stay on their place? Maybe there are some beautiful solutions?
It has been 2 weeks since I asked the question and as I got back to work I found solution myself. Maybe anyone find it helpful. So the idea was to split string into parts divided by "<" and ">". And then we can check whether each part is html tag or not and add highlight only to text parts.
So here is the code. There are things to be improved but still it worked well for my case.
class Highlighter {
static hlcolors: Map<IHlType, string> = new Map([
[IHlType.success, 'success'],
[IHlType.highlight, 'currHl']
]);
static getHlVal(value: string, type: IHlType): string {
let clazz = Highlighter.hlcolors.get(type);
return '<span class="' + clazz + '">' + value + '</span>';
}
static hlByPhrase(value: string, type: IHlType, phrase: string): string {
return value.replace(phrase, Highlighter.getHlVal(phrase, type));
}
static parsehl(value: string, type: IHlType, phrase: string){
let temp = [];
let temp1 = value;
while(temp1.length > 0){
let stPos = temp1.indexOf("<");
let enPos = temp1.indexOf(">");
if(stPos === 0){
temp.push(temp1.slice(stPos, enPos+1));
temp1 = temp1.slice(enPos+1);
}
else {
temp.push(temp1.slice(0, stPos));
temp1 = temp1.slice(stPos);
}
}
let res = "";
for(let i = 0; i<temp.length; i++){
if(temp[i].includes("<div") || temp[i].includes("<span") || temp[i].includes("</div") || temp[i].includes("</span"))
res += temp[i];
else res += temp[i].replace(phrase, Highlighter.getHlVal(phrase, type));
}
return res;
}
}

MVC View adding in quotations to html attribute

I am working on a small project and in the partial navigation view I am checking if a page is selected and highlighting the menu.
var controller = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString().ToLower();
var home = string.Empty;
var content = string.Empty;
switch(controller) {
case "home":
home = "class=current";
break;
case "content":
content = "class=current";
break;
}
In the view I am then doing:
<li #home>Home</li>
Originally in my code I had
home = "class='current'";
Notice I had quotations around it, but when I executed the code the html source looks like
So when I remove the quatations and run it again, since it's adding them in by default, it works, even though the debugger looks like
So the project is working, my question is why is it by default adding in the quotations?
I'm not certain that MVC is adding the quotes, that is probably the Chrome DevTools doing it. If you "View page source", I don't think you will see the quotes.
Just FYI, because of these kinds of things I usually don't include the attribute in such strings, just the value...
<li class="#home">
MVC doesn't add quotes for #home. If you decompile this page, you could get codes like below:
public class _Page_Views_Home_Index_cshtml : WebViewPage<object>
{
// Methods
public override void Execute()
{
((dynamic) base.ViewBag).Title = "Home Page";
base.BeginContext("~/Views/Home/Index.cshtml", 0x27, 2, true);
this.WriteLiteral("\r\n");
base.EndContext("~/Views/Home/Index.cshtml", 0x27, 2, true);
string str = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
string str2 = string.Empty;
string str3 = string.Empty;
string str4 = str;
if (str4 != null)
{
if (!(str4 == "Home"))
{
if (str4 == "content")
{
str3 = "class=current";
}
}
else
{
str2 = "class=current";
}
}
base.BeginContext("~/Views/Home/Index.cshtml", 0x1a6, 9, true);
this.WriteLiteral("\r\n\r\n<div ");
base.EndContext("~/Views/Home/Index.cshtml", 0x1a6, 9, true);
base.BeginContext("~/Views/Home/Index.cshtml", 0x1b0, 4, false);
this.Write(str2);
....
}
}
The Write methods will finally calls WebUtility.HtmlDecode method, this method replaces special chars, but will not add quotes.
Hope this helps.

Mule - how to pad rows in a CSV file with extra delimiters

I have a CSV file coming into my Mule application that looks as follows:
1,Item,Item,Item
2,Field,Field,Field,Field
2,Field,Field,Field,Field
3,Text
Is there a way I can transform this file in Mule to something like the below:
1,Item,Item,Item,,,,,,
2,Field,Field,Field,Field,,,,,
2,Field,Field,Field,Field,,,,,
3,Text,,,,,,,,
Essentially, what I need to do here is append a string (containing x occurrences of a delimiter) to the end of each row. The number of delimiters I need to append to each row can be determined by the first character of that row e.g. if row[0]='1' then (append ",,,,,,") else if row[0]='2' then (append ",,,,,"etc.
The reason I have this rather annoying problem is because the system providing the input to my Mule application produces a file where the number of columns in each row may vary. I'm trying to pad this file so that the number of columns in each row is equal, so that I can pass it on to a Java transformer like the one explained here that is using FlatPack (which expects x columns, it won't accept a file that has a varying number of columns in each row).
Does anyone have any ideas on how I could approach this? Thanks in advance.
UPDATE
Based on #Learner's recommendation and #EdC's answer - I've achieved this in Mule using the below:
<flow name="testFlow1" doc:name="testFlow1">
<file:inbound-endpoint .../>
<file:file-to-string-transformer doc:name="File to String"/>
<component doc:name="Java" class="package.etc.etc.MalformData"/>
</flow>
Try this based on #Learner 's answer.
import org.mule.api.MuleEventContext;
import org.mule.api.MuleMessage;
public class MalformData implements org.mule.api.lifecycle.Callable {
private String[] strTempArray;
public String findMalformRow(String strInput) {
String strOutput = "";
String strFix = "";
int intArrayLength = 0;
char charFirst = ' ';
String strControl = "";
strTempArray = strInput.split("\\n");
intArrayLength = strTempArray.length;
for (int i = 0; i < intArrayLength; i++) {
charFirst = strTempArray[i].charAt(0);
strFix = strTempArray[i];
String missingDelimiter = "";
if (charFirst == '1') {
missingDelimiter = ",,,,,,";
strFix += missingDelimiter;
} else if (charFirst == '2') {
missingDelimiter = ",,,,,";
strFix += missingDelimiter;
} else if (charFirst == '3') {
missingDelimiter = ",,,,,,,,";
strFix += missingDelimiter;
} else {
strFix = "Good";
}
if (strControl != "Good") {
strTempArray[i] = strFix;
} else {
charFirst = ' ';
strFix = "";
}
}
for(int i=0; i < intArrayLength; i++){
strOutput += strTempArray[i] + "\n";
}
return strOutput;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage message = eventContext.getMessage();
String newPayload = this.findMalformRow(message.getPayloadAsString());
message.setPayload(newPayload);
return message;
}
}
You could write a custom java component that reads your CSV file line by line, write to another file and add , based on your logic at the end of each line