Find in XML and read only that part - c#-4.0

I have an XML file with some login information that I need to search for login name, and find relevant data for the account.
The XML file I have looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!--GroupTool2 bot settings file-->
<!--Please do not make any manual changes to this file!-->
<GroupTool2_Settings>
<SavedBots>
<BotName>Midday Ibor</BotName>
<BotPass>Password Hash</BotPass>
<BotMaster>Master Trapper</BotMaster>
<BotGroup>MyGroup</BotGroup>
<StartLocation>#Home/</StartLocation>
<DontSend>1</DontSend>
<DaysBetweenInvited>11</DaysBetweenInvited>
</SavedBots>
<SavedBots>
...
</SavedBots>
</GroupTool2_Settings>
What I need to do, is to be able to search the document for the BotName, and only read the data between that is relevant to the BotName I am searching for.
But there are moe troubles along the way.
The BotName are not always stored as "FirstName LastName", it could also be stored as "FirstName" and "FirstName.LastName"
The variables I will always have aailable to search for, however, is ALWAYS the string BotFName and BotLname. In the cases that the saved BotName is only FirstName, the LastName used will always be a certain name, so the LastName could simply just be dropped when it comes to search for the name in the document.
I am also not the author of the XML document in question, so it can not be changed to simplify my search.
I am however not looking for a full solution, just a short pseudo example so I know where to begin.
Any help is apreciated.
/Rickard

You may search an element via Linq-XML.
XDocument doc = XDocument.Load(file);
string search="Midday Ibor";
var savedBots = doc.Descendants("SavedBots").Where(p => p.Element("BotName").Value == search).FirstOrDefault();
if (savedBots != null)
{
Console.WriteLine((string)savedBots.Element("BotPass"));
}

Related

PDFTron: What is the proper way to find date fields in a PDF form

[PdfTron 5.2]
I have a PDF form with text and date fields. I want to find the date fields.
I can get the actions of the field with getActions().
field.getActions()
returns
{"F":[{"yc":"JavaScript","Gt":"AFDate_FormatEx(\"dd.mm.yyyy\");"}],
"K":[{"yc":"JavaScript","Gt":"...);","ey":null}]}
As you can see, the date is in actions.F[0].Gt. But checking actions.F[0].Gt
for "AFDate" seems wrong, that's too low-level.
Is there a better API function to find out, that I have a date field?
Thank you.
You are correct. The Gt property is obfuscated and minified which is volatile and not meant to be used. If you require an API, you should refer to our documentation. Everything should be available there except a few (one of which will be used below), but feel free to contact us if you do need help!
Unfortunately, there is no API currently to get that type. From my limited understanding, the "type" of a field is determined by the attached actions and not simply a specific type or flag. This suggests all fields are just text fields with special formatting actions to make it look and feel like its a date or numeric field.
In this case, you will have to check the formatting action (F) as you have already noticed for the date formatting function (AFDate_FormatEx). To get the JavaScript from that action, you should use the javascript property on the action which was not in the documentation. However, you can see it if you console log the action.
Here is an example:
const dateActionJs = /.+:"AFDate_FormatEx\(.*/;
instance.docViewer.on('annotationsLoaded', () => {
const annotations = annotManager.getAnnotationsList();
annotations.forEach(annot => {
const actions = annot.getField().getActions();
if (actions.F && actions.F[0] && actions.F[0].javascript && dateActionJs.test(actions.F[0].javascript)) { // F = Format Action
console.log('Found Date');
}
});
});
Let me know if this helps!
EDIT: You can search for AFDate instead of AFDate_FormatEx which will be sufficient.

xpages copy field value to another field from other datasource

I followed How do you copy a datetime field from the current document to a new document and I try something like this:
Cdoc.save();
Pdoc.copyItem(Cdoc.getDocument().getFirstItem("mytest1"));
getComponent('exampleDialog').show()
But I get a handling error message.
Thanks for your time!
Assuming Cdoc and Pdoc are defined as xp:dominoDocument data sources then you have to change your code to:
Cdoc.save();
Pdoc.getDocument().copyItem(Cdoc.getDocument().getFirstItem("mytest1"));
getComponent('exampleDialog').show()
So, you only need to add .getDocument() to Pdoc to get the Notes Document. Otherwise it fails and you get the error "Error calling method 'copyItem(lotus.domino.local.Item)' on an object of type 'NotesXspDocument'".
Keep in mind that you have to save Pdoc after copying item too if you want to show the copied item in your exampleDialog.
If you don't want to save document Pdoc at this point yet then you can copy the item on NotesXspDocument level with just:
Pdoc.replaceItemValue("mytest1", Cdoc.getItemValueDateTime("mytest1"));
getComponent('exampleDialog').show()
I do not often use "copyItem". You are not specifying if you are using NotesDocuments or NotesXspDocuments, so I will write a quick thing about both because they should be handled differently.
var currentDoc:NotesDocument = ....
var newDoc:NotesDocument= ...
newDoc.replaceItemValue("fldname", currentDoc.getItemValueDateTimeArray("fldname").elementAt(0))
if currentDoc is a NotesXspDocument, use the following
var currentDoc:NotesXspDocument = ...
var newDoc:NotesDocument=...
newDoc.replaceItemValue("fldname", currentDoc.getItemValueDateTime("fldname"))
Otherwise, you could continue trying with copyItem, I just lack experience with it.
EDIT
Just some things to add, remember that putting calling xspDoc.getDocument(true) will update the background document and this might be needed. Also, in the comments for that article you posted, they mentioned the possible need to put that document into another variable.
var docSource:NotesDocument = xspDoc.getDocument(true);
var docNew:NotesDocument = ...
docNew.copyItem(docSource.getItem("blah");
Also remember that copyItem is a function of NotesDocument and not NotesXspDocument.

Customize the search portlet in Plone for specific content types

I'm using the search portlet in certain areas of my website, but I'd like to restrict the results to only search for a specific content type: for example only search the news items, or only show Faculty Staff Directory profiles.
I know you can do this after you get to the ##search form through that "filter" list, but is there a way to start with the filter on, so that the "Live Search" results only show the relevant results (i.e. only news items or only profiles).
I suspect you know it already, but just to be sure: You can globally define which types should be allowed to show up in searchresults in the navigations-settings of the controlpanel, and then export and include the relevant parts to your product's GS-profile-propertiestool.xml.
However, if you would like to have some types excluded only in certain sections, you can customize Products.CMFPlone/skins/plone_scripts/livesearch_reply, which already filters the types, to only show "friendly_types" around line 38 (version 4.3.1) and add a condition like this:
Edit:
I removed the solution to check for the absolute_url of the context, because the context is actually the livesearch_reply in this case, not the current section-location. Instead the statement checks now, if the referer is our section:
REQUEST = context.REQUEST
current_location = REQUEST['HTTP_REFERER']
location_to_filter = '/fullpath/relative/to/siteroot/sectionId'
url_to_filter = str(portal_url) + location_to_filter
types_to_filter = ['Event', 'News Item']
if current_location.find(url_to_filter) != -1 or current_location.endswith(url_to_filter):
friendly_types = types_to_filter
else:
friendly_types = ploneUtils.getUserFriendlyTypes()
Yet, this leaves the case open, if the user hits the Return- or Enter-key or the 'Advanced search...'-link, landing on a different result-page than the liveresults have.
Update:
An opportunity to apply the filtering to the ##search-template can be to register a Javascript with the following content:
(function($) {
$(document).ready(function() {
// Let's see, if we are coming from our special section:
if (document.referrer.indexOf('/fullpath/relative/to/siteroot/sectionId') != -1) {
// Yes, we have the button to toggle portal_type-filter:
if ($('#pt_toggle').length>0) {
// If it's checked we uncheck it:
if ($('#pt_toggle').is(':checked')) {
$('#pt_toggle').click();
}
// If for any reason it's not checked, we check and uncheck it,
// which results in NO types to filter, for now:
else {
$('#pt_toggle').click();
$('#pt_toggle').click();
}
// Then we check types we want to filter:
$("input[value='Event']").click();
$("input[value='News Item']").click();
}
}
})
})(jQuery);
Also, the different user-actions result in different, inconsistent behaviours:
Livesearch accepts terms which are not sharp, whereas the ##search-view only accepts sharp terms or requires the user to know, that you can append an asterix for unsharp results.
When hitting the Enter/Return-key in the livesearch-input, the searchterm will be transmitted to the landing-page's (##search) input-element, whilst when clicking on 'Advanced search...' the searchterm gets lost.
Update:
To overcome the sharp results, you can add this to the JS right after the if-statement:
// Get search-term and add an asterix for blurry results:
var searchterm = decodeURI(window.location.search.replace(new RegExp("^(?:.*[&\\?]" + encodeURI('SearchableText').replace(/[\.\+\*]/g, "\\$&") + "(?:\\=([^&]*))?)?.*$", "i"), "$1")) + '*';
// Insert new searchterm in input-text-field:
$('input[name=SearchableText]').val(searchterm);
Update2:
In this related quest, Eric Brehault provides a better solution for passing the asterix during submit: Customize Plone search
Of course you can also customize the target of advanced-search-link in livesearch_reply, respectively in the JS for ##search, yet this link is rather superfluous UI-wise, imho.
Also, if you're still with Archetypes and have more use-cases for pre-filtered searchresults depending on the context, I can recommend to have a look at collective.formcriteria, which allows to define search-criteria via the UI. I love it for it's generic and straightforward plone-ish approach: catalogued indizi and collections. In contradiction to eea.facetednavigation it doesn't break accessibility and can be enhanced progressively with some live-search-js-magic with a little bit of effort, too. Kudos to Ross Patterson here! Simply turn a collection (old-style) into a searchform by changing it's view and it can be displayed as a collection-portlet, as well. And you can decide which criteria the user should be able to change or not (f.e. you hide the type-filter and offer a textsearch-input).
Watch how the query string changes when you use the filter mechanism on the ##search page. You're simply adding/subtracting catalog query criteria.
You may any of those queries in hidden fields in a search form. For example:
<form ...>
....
<input type="hidden" name="portal_type" value="Document" />
</form>
The form on the query string when you use filter is complicated a bit by its record mechanism, which allows for some min/max queries. Simple filters are much easier.

Setting a document field with replaceItemValue from a rich text control?

How do you set a richText value with replaceItemValue from a rich tect control?
I found this bit of code here:
http://www.bleedyellow.com/blogs/martin/entry/save_a_richtext_field_from_a_xpage_to_a_document?lang=en_us
var doc = configuratieformulieren.getDocumentByKey("ConfiguratieIVNL", true);
if(doc == null){
return;
}else{
var titel = getComponent("inputTextIBPTitelIVNL").getValue();
doc.replaceItemValue("IBPTitel",titel);
var inhoud = getComponent("inputRichTextIBPInhoudIVNL").getValue();
if (inhoud != null){
var contentType = doc.getMIMEEntity("IBPInhoud").getContentType();
var encoding = doc.getMIMEEntity("IBPInhoud").getEncoding();
var str = session.createStream();
inhoud.toString();
str.writeText(inhoud.toString());
doc.getMIMEEntity("IBPInhoud").setContentFromText(str, contentType, encoding);
}
doc.save(true, true);
}
sessionScope.put("FormulierIVNLInfoBeschPG","Lezen");
Is it correct? It looks like this code depends on the fact that the field already exists. How id this handled if the field does not exist? Is there and easier way to set a field value to the contents of a rich text control?
Let data sources do the heavy lifting. For a long and boring (but thorough) explanation of why, read this article. But here's the quick version:
Don't use:
getComponent("someID").getValue()
Instead, use:
someDataSource.getValue("someFieldName")
This is always a more efficient way to access data: instead of having to spider through the component tree to locate a match, it goes straight to the data source, which the component would have to ask anyway if you asked it what its value is.
Similarly, don't use:
someDataSource.replaceItemValue("someFieldName", someValue)
Instead, use:
someDataSource.setValue("someFieldName", someValue)
The latter is much more flexible on input type. The data source already contains all the logic for determining what to do based on whether the value is text, date, number, rich text, file upload, etc. No need to duplicate any of that logic in your own code.
So if the goal is to update a separate document based on data in the current document, just define a separate document data source that points to the document you want to update. Then it's literally this simple:
configData.setValue("RichTextData", currentDocument.getValue("RichTextData"));
configData.save();
With the above code, if the field you specify on the current document is rich text, then the item it creates on the other document will be rich text. If it's any other type on the current document, it will be the same type on the other document. With getValue() and setValue(), you don't have to pay attention to the data type... the data source handles all of that for you.
For bonus points, scope configData to applicationScope so that any updates to it are immediately cached for all users... or sessionScope if the document you're updating is user-specific.
I was able to solve my orginal issue. To expand on my issue I was having problems with using a dialog box to create Form / Document B from Form / Document A using a dialog box on Form A. What was happening was any changes to Form B would be saved to Document A's datasource.
I found the ingoreRequestParams on Form B's datasource, set it and that solved my problem with Form B writing to Form A document.

Exact phrase search using Lucene.net

I am having trouble searching for an exact phrase using Lucene.NET 2.0.0.4
For example I am searching for "scope attribute sets the variable" (including quotes) but receive no matches, I have confirmed 100% that the phrase exists.
Can anyone suggest where I am going wrong? Is this even supported with Lucene.NET? As usual the API documentation is not too helpful and a few CodeProject articles I've read don't specifically touch on this.
Using the following code to create the index:
Directory dir = Lucene.Net.Store.FSDirectory.GetDirectory("Index", true);
Analyzer analyzer = new Lucene.Net.Analysis.SimpleAnalyzer();
IndexWriter indexWriter = new Lucene.Net.Index.IndexWriter(dir, analyzer,true);
//create a document, add in a single field
Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();
Lucene.Net.Documents.Field fldContent = new Lucene.Net.Documents.Field(
"content", File.ReadAllText(#"Documents\100.txt"),
Lucene.Net.Documents.Field.Store.YES,
Lucene.Net.Documents.Field.Index.TOKENIZED);
doc.Add(fldContent);
//write the document to the index
indexWriter.AddDocument(doc);
I then search for a phrase using:
//state the file location of the index
Directory dir = Lucene.Net.Store.FSDirectory.GetDirectory("Index", false);
//create an index searcher that will perform the search
IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(dir);
QueryParser qp = new QueryParser("content", new SimpleAnalyzer());
// txtSearch.Text Contains a phrase such as "this is a phrase"
Query q=qp.Parse(txtSearch.Text);
//execute the query
Lucene.Net.Search.Hits hits = searcher.Search(q);
The target document is about 7 MB plain text.
I have seen this previous question however I don't want a proximity search, just an exact phrase search.
Shashikant Kore is correct with his answer, you need to enable term positions...
However, I would recommend not storing the text of the document in the field unless you absolutely need it to return back to you in the search results... Setting the store to 'NO' might help reduce the size of your index a bit.
Lucene.Net.Documents.Field fldContent =
new Lucene.Net.Documents.Field("content",
File.ReadAllText(#"Documents\100.txt"),
Lucene.Net.Documents.Field.Store.NO,
Lucene.Net.Documents.Field.Index.TOKENIZED,
Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS);
You have not enabled the term positions. Creating field as follows should solve your problem.
Lucene.Net.Documents.Field fldContent =
new Lucene.Net.Documents.Field("content",
File.ReadAllText(#"Documents\100.txt"),
Lucene.Net.Documents.Field.Store.YES,
Lucene.Net.Documents.Field.Index.TOKENIZED,
Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS);

Resources