Selecting more than one attribute from xml file - xpath

I have an xml file. In the file there are some elements with some attributes.
I want to select the attributes age and height to put in a dropdown box. If I do the following, I get the age displayed in the drop-down box.
var q = this.test;
var a = (this.lastForm = isoNS.curForm).selectNodes("*[#COLNAME='AGE']"), g = a.length;
q.removeAll();
while(g--)q.add({isoCID: a[g].getAttribute("ISOCID"),
label: a[g].getAttribute("COLNAME")});
To get the height displayed, I have tried the following (among other thing), but doesn't work
var a = (this.lastForm = isoNS.curForm).selectNodes("*[#COLNAME='AGE' and #COLNAME='HEIGHT']"), g = a.length;
How do I get both values?

If you are using XML files with the same structure in your program, it is better to create a serializable class for it using "Paste XML as classes" command in Visual Studio. Then you will be able to operate it much easier, without getting tired with a hard-code approach like using Xpath

Related

kendo ui editor how to modify user selection with range object

Kendo UI 2015.2.805 Kendo UI Editor for Jacascript
I want to extend the kendo ui editor by adding a custom tool that will convert a user selected block that spans two or more paragraphs into block of single spaced text. This can be done by locating all interior p tags and converting them into br tags, taking care not to change the first or last tag.
My problem is working with the range object.
Getting the range is easy:
var range = editor.getRange();
The range object has a start and end container, and a start and end offset (within that container). I can access the text (without markup)
console.log(range.toString());
Oddly, other examples I have seen, including working examples, show that
console.log(range);
will dump the text, however that does not work in my project, I just get the word 'Range', which is the type of the object. This concerns me.
However, all I really need however is a start and end offset in the editor's markup (editor.value()) then I can locate and change the p's to br's.
I've read the telerik documentation and the referenced quirksmode site's explanation of html ranges, and while informative nothing shows how to locate the range withing the text (which seems pretty basic to me).
I suspect I'm overlooking something simple.
Given a range object how can I locate the start and end offset within the editor's content?
EDIT: After additional research it appears much more complex than I anticipated. It seems I must deal with the range and/or selection objects rather than directly with the editor content. Smarter minds than I came up with the range object for reasons I cannot fathom.
Here is what I have so far:
var range = letterEditor.editor.getRange();
var divSelection;
divSelection = range.cloneRange();
//cloning may be needless extra work...
//here manipulate the divSelection to how I want it.
//divSeletion is a range, not sure how to manipulate it
var sel = letterEditor.editor.getSelection()
sel.removeAllRanges();
sel.addRange(divSelection);
EDIT 2:
Based on Tim Down's Solution I came up with this simple test:
var html;
var sel = letterEditor.editor.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
html = html.replace("</p><p>", "<br/>")
var range = letterEditor.editor.getRange();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = html;
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
range.insertNode(frag);
The first part, getting the html selection works fine, the second part also works however the editor inserts tags around all lines so the result is incorrect; extra lines including fragments of the selection.
The editor supports a view html popup which shows the editor content as html and it allows for editing the html. If I change the targeted p tags to br's I get the desired result. (The editor does support br as a default line feed vs p, but I want p's most of the time). That I can edit the html with the html viewer tool lets me know this is possible, I just need identify the selection start and end in the editor content, then a simple textual replacement via regex on the editor value would do the trick.
Edit 3:
Poking around kendo.all.max.js I discovered that pressing shift+enter creates a br instead of a p tag for the line feed. I was going to extend it to do just that as a workaround for the single-space tool. I would still like a solution to this if anyone knows, but for now I will instruct users to shift-enter for single spaced blocks of text.
This will accomplish it. Uses Tim Down's code to get html. RegEx could probably be made more efficient. 'Trick' is using split = false in insertHtml.
var sel = letterEditor.editor.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
var block = container.innerHTML;
var rgx = new RegExp(/<br class="k-br">/gi);
block = block.replace(rgx, "");
rgx = new RegExp(/<\/p><p>/gi);
block = block.replace(rgx, "<br/>");
rgx = new RegExp(/<\/p>|<p>/gi);
block = block.replace(rgx, "");
letterEditor.editor.exec("insertHtml", { html: block, split: false });
}

How to get the entire Visual Studio active document... with formatting

I know how to use VS Extensibility to get the entire active document's text. Unfortunately, that only gets me the text and doesn't give me the formatting, and I want that too.
I can, for example, get an IWpfTextView but once I get it, I'm not sure what to do with it. Are there examples of actually getting all the formatting from it? I'm only really interested in text foreground/background color, that's it.
Note: I need the formatted text on every edit, so unfortunately doing cut-and-paste using the clipboard is not an option.
Possibly the simplest method is to select all of the text and copy it to the clipboard. VS puts the rich text into the clipboard, so when you paste, elsewhere, you'll get the colors (assuming you handle rich text in your destination).
Here's my not-the-simplest solution. TL;DR: you can jump to the code at https://github.com/jimmylewis/GetVSTextViewFormattedTextSample.
The VS editor uses "classifications" to show segments of text which have special meaning. These classifications can then be formatted differently according to the language and user settings.
There's an API for getting the classifications in a document, but it didn't work for me. Or other people, apparently. But we can still get the classifications through an ITagAggregator<IClassificationTag>, as described in the preceding link, or right here:
[Import]
IViewTagAggregatorFactoryService tagAggregatorFactory = null;
// in some method...
var classificationAggregator = tagAggregatorFactory.CreateTagAggregator<IClassificationTag>(textView);
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
var tags = classificationAggregator.GetTags(wholeBufferSpan);
Armed with these, we can rebuild the document. It's important to note that some text is not classified, so you have to piece everything together in chunks.
It's also notable that at this point, we have no idea how any of these tags are formatted - i.e. the colors used during rendering. If you want to, you can define your own mapping from IClassificationType to a color of your choice. Or, we can ask VS for what it would do using an IClassificationFormatMap. Again, remember, this is affected by user settings, Light vs. Dark theme, etc.
Either way, it could look something like this:
// Magic sauce pt1: See the example repo for an RTFStringBuilder I threw together.
RTFStringBuilder sb = new RTFStringBuilder();
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
// Magic sauce pt2: see the example repo, but it's basically just
// mapping the spans from the snippet above with the formatting settings
// from the IClassificationFormatMap.
var textSpans = GetTextSpansWithFormatting(textBuffer);
int currentPos = 0;
var formattedSpanEnumerator = textSpans.GetEnumerator();
while (currentPos < wholeBufferSpan.Length && formattedSpanEnumerator.MoveNext())
{
var spanToFormat = formattedSpanEnumerator.Current;
if (currentPos < spanToFormat.Span.Start)
{
int unformattedLength = spanToFormat.Span.Start - currentPos;
SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, unformattedLength);
sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}
System.Drawing.Color textColor = GetTextColor(spanToFormat.Formatting.ForegroundBrush);
sb.AppendText(spanToFormat.Span.GetText(), textColor);
currentPos = spanToFormat.Span.End;
}
if (currentPos < wholeBufferSpan.Length)
{
// append any remaining unformatted text
SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, wholeBufferSpan.Length - currentPos);
sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}
return sb.ToString();
Hope this helps with whatever you're doing. The example repo will ask if you you want the formatted text in the clipboard after each edit, but that was just a dirty way that I could test and see that it worked. It's annoying, but it was just a PoC.

Using Javascript for Automation to copy cells in Numbers

I want to use JXA to automate some updating of Numbers spreadsheets. For example, copying a range of cells from one spreadsheet to another one with a different structure.
At this point, I'm just testing a simple program to set or read the value of a cell and I can't get this to work.
When I try to set a value I get "Error -1700: Can't convert types." and when I try to read a value I get back a [object ObjectSpecifier] rather than a text or number value.
Here's an example of the code:
Numbers = Application('Numbers')
Numbers.activate()
delay(1)
doc = Numbers.open(Path('/Users/username/Desktop/Test.numbers'))
currentSheet = doc.Sheets[0]
currentTable = currentSheet.Tables[0]
console.log(currentTable['name'])
console.log(currentTable.cell[1][1])
currentTable.cell[1][1].set(77)
When I run this, I get and output of [object ObjectSpecifier] for the two console.logs and then an error -1700: Can't convert types when it tries to set a cell.
I've tried several other variations of accessing or setting properties but can't get it to work.
Thanks in advance,
Dave
Here is a script that sets and gets a cell's value and then sets a different cell's value in the same table:
// Open Numbers document (no activate or delay is needed)
var Numbers = Application("Numbers")
var path = Path("/path/to/spreadsheet.numbers")
var doc = Numbers.open(path)
// Access the first table of the first sheet of the document
// Note:
// .sheets and .tables (lowercase plural) are used when accessing elements
// .Sheet and .Table (capitalized singular) are used when creating new elements
var sheet = doc.sheets[0]
var table = sheet.tables[0]
// Access the cell named "A1"
var cell = table.cells["A1"]
// Set the cell's value
cell.value = 20
// Get the cell's value
var cellValue = cell.value()
// Set that value in a different cell
table.cells["B2"].value = cellValue
Check out the Numbers scripting dictionary (with JavaScript selected as the language) to see classes and their properties and elements. The elements section will show you the names of elements (e.g. the Document class contains sheets, the Sheet class contains tables, and so on). To open the scripting dictionary, in Script Editor's menu bar, choose Window > Library, and then select Numbers in the library window.
In regards to the logging you were seeing - I recommend using a function similar to this:
function prettyLog(object) {
console.log(Automation.getDisplayString(object))
}
Automation.getDisplayString gives you a "pretty print" version of any object you pass to it. You can then use that for better diagnostic logging.

Programatically updating underlying data in Slickgrid

I have 6 textboxes at the top of the screen that update an entire column(one textbox per column) based on any changes. I was selecting the columns based on their class (.l#). Here is the code (issues to follow):
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = [".l1", ".l7", ".l8", ".l9"];
var fields = $(bound[id]);
for (var i = 0; i < fields.length; i++)
{
fields[i].innerHTML = $(ctrl).val();
}
};
which is bound to the keyup event for the text areas. Issues are:
1) initially fields.length was -1 as I didn't want to put data in the "add new
row" section at the bottom. However, when running it, I noticed the
final "real" record wasn't being populated. Also, when stepping through, I
noticed that the "new row" field was before the "last row" field.
2) when doing it this way, it is purely superficial: if I double click the field,
the real data hasn't been changed.
so in the grand scheme of things, I know that I was doing it wrong. I'm assuming it involves updating the data and then forcing a render, but I'm not certain.
Figured out how to do it. Modified the original code this way:
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = ['title1', 'title2', 'title3', 'title4'];
var field = bound[id];
for (var i = 0; i < dataView.getLength(); i++)
{
var item = dataView.getItem(i);
item[field] = $(ctrl).val();
dataView.updateItem(i, item);
}
grid.invalidate();
};
I have 6 textboxes (item1-item6) that "bind" to fields in the sense that if I change data in a textbox, it updates all of the rows and any new rows added also have this data.
Parts where the two issues can be explained this way:
1) to work around that, though still it would be a presentational fix and not a real updating of the underlying data, one could force it to ignore if it had the active class attached. Extra work, and not in the "real" direction one is going for (masking the field).
2) It was pretty obvious with the original implementation (though it was all I could figure out via Chrome Dev Tools that I could modify at the time) that it was merely updating a div's content and not actually interacting with the data underneath. Would look nice, and perhaps one could just pull data from the item1-item6 boxes in place of the column if it is submitted, but if someone attempts to modify the cell, they'll be looking at the real data again.

ActiveReports as a convert to pdf machine

The company I'm with is likely to obtain an ActiveReports 7 license. There's a new project requirement that several webgrids (not actually webgrids, but more like html rendered with zurb) need to be converted into pdfs. At one point in the code behind they're effectively datasets or can be created into such. Is there a way to shuttle the data from the datasets into active reports, then render it out as a PDF. I'd like to keep the report as generic as possible, and thus have one active report for all the datatables, so doing using active reports as its usually done is kind of out of the question.
The only thing I can think of at the moment is a single textbox in the group header into which I could concatenate all the headers, and a single textbox in the details into which I could throw all the data for each row. The problem here is that I'd run into many formatting issues as nothing would line up properly - as tab delimiting would solve nothing here. I could have multiple textboxes with various spacing, but then it would eventually devolve into a different report for each dataset. Is it possible to apply some sort of markup so that I could keep the spacing of columns as I feed the data in. Do active reports richtextboxes honor html markup? Or is there another solution altogether?
I'd use Itextsharp, but its not free for commercial products.
Thanks,
Sam
You can dynamically build a report that will output a simple table based on a specified DataSet, well actually a System.Data.DataTable. Basically for each column in the DataTable, add a textbox to the header to hold the name of the column and add another textbox to the Detail section to hold the value.
For the textbox in the detail section set its DataField property to the name of the column. With the binding in place, you can set the report's DataSource property to the DataTable and then run the report and export it to PDF.
The following code is a basic example:
var left = 0f;
var width = 1f;
var height = .25f;
var space = .25f;
var rpt = new SectionReport();
rpt.Sections.Add(SectionType.ReportHeader, "rh").Height = height;
rpt.Sections.Add(SectionType.Detail, "detail").Height = height;
rpt.Sections.Add(SectionType.ReportFooter, "rf").Height = height;
foreach (System.Data.DataColumn col in dataTable.Columns)
{
var txt = new TextBox { Location = new PointF(left, 0), Size = new SizeF(width, height) };
txt.Text = col.ColumnName;
rpt.Sections["rh"].Controls.Add(txt);
txt = new TextBox { Location = new PointF(left, 0), Size = new SizeF(width, height) };
txt.DataField = col.ColumnName;
rpt.Sections["detail"].Controls.Add(txt);
left += width + space;
}
rpt.DataSource = dataTable;
rpt.Run();
var pdf = new PdfExport();
pdf.Export(rpt.Document, #"c:\Users\scott\downloads\test.pdf");

Resources