What does `namespaceMappings` mean in Word.CustomXMLPart API - ms-word

I have created a small snippet in Script Lab which basically:
Creates a custom XML:
<AP xmlns="accordproject.org">
<template xmlns="acceptance-of-delivery">
<shipper>Aman Sharma</shipper>
</template>
</AP>
Tries to query this xml by using the xPath /AP/template. I run this block of code:
await Word.run(async context => {
const customXmlParts = context.document.customXmlParts;
const AP = customXmlParts.getByNamespace("accordproject.org").getOnlyItemOrNullObject();
await context.sync();
const nodes = AP.query('/AP/template', {}); // how does this work?
await context.sync();
console.log(nodes);
})
Deletes the customXML.
The second argument of query API is namespaceMappings. I think I am passing that incorrectly and that's why I get this as ouput (empty object).
But when I pass * instead of /AP/template, I get the whole XML (while the second argument, namespaceMappings remain the same).
Where am I going wrong? Can anyone share some snippets to help me query customXML.

The short answer is that you can use
const nodes = AP.query("/n1:AP/n2:template", {n1:"accordproject.org", n2:"acceptance-of-delivery"});
I don't know JS/TS at all but I assume these are basically key-value pairs of some kind. You can also use
const nodes = AP.query("/n1:AP/n2:template", {"n1":"accordproject.org", "n2":"acceptance-of-delivery"});
if you prefer to think of the Namespace prefixes as strings.
(For anyoneunfamiliar, the "n1" and "n2" are just prefixes that you invent so you can reference the full Namespace URIs. They don't have anything to do with any prefixes you might have used in the piece of XML you are querying.)
I couldn't find documentation on this either and originally assumed you might need something more like { Prefix:"ns1", namespaceURI:"the namespace URI" }, but that's just because those are the property names used in the VBA model.

Related

Are getter functions necessary for Protractor element locators

When using PageObjects for Protractor e2e tests, should you use getter functions for the element locator variables instead of having variables?
example:
public loginButton: ElementFinder = $('#login-submit');
public loginUsername: ElementFinder = $('#login-username');
Or should you use a getter function in the Page Object like this:
public get loginButton(): ElementFinder {
return $('#login-submit');
}
public get loginUsername(): ElementFinder {
return $('#login-username');
}
Is one approach better than another?
No getters needed, since protractor ElementFinder and ElementArrayFinder objects are lazy - no any searching for this element will be done until you will try to call some methods on them. Actually thats also a reason why you don't need to use await for protractor element search methods:
const button = $('button') // no await needed, no getter needed
console.log('Element is not yet tried to be searched on the page')
await button.click() // now we are sending 2 commands one by one - find element and second - do a click on found element.
http://www.protractortest.org/#/api?view=ElementFinder
ElementFinder can be used to build a chain of locators that is used to find an element. An ElementFinder does not actually attempt to find the element until an action is called, which means they can be set up in helper files before the page is available.
It's fine to use either but if you're going to transform or do something else to your element, then the getter function would be better in my opinion since that's the reason why we utilize mutators in the first place.
I'm not really sure which method is more convenient, if there is one.
I've been using protractor for a bit longer than 1 year now, and I always stored locators in variables.
What I'd normally do is:
const button = element(by.buttonText('Button'));
Then I'd create a function for interacting with the element:
const EC = protractor.ExpectedConditions;
const clickElement = async (element) => {
await browser.wait(EC.elementToBeClickable(element));
await element.click();
};
Finally, use it:
await clickElement(button);
Of course I store the locators and functions in a page object, and invoking/calling them in the spec file. It's been working great so far.

vscode - Is there a way to create an instance of `vscode.TextDocument`?

I'm listening for onWillSaveTextDocument and getting an instance of vscode.TextDocument which I use for file content and file path information.
It would be convenient to just create a new instance of this object, rather than recreating all of the information from a file path.
I'm hoping there is something like:
const document = new TextDocument(myFilePath);
You could simply use vscode.workspace.openTextDocument method to create TextDocument instance.
An example would be:
vscode.workspace.openTextDocument( {
language: 'text'
} )
.then( doc => {
// Do something useful with the document.
});
If you'd like to see it used in context, feel free to see this part of code.

OwinContext.Request multi-part/form-data parsing?

Is there an easy way to parse multi-part/form-data information from an OwinContext.Request instance?
I know how to do this using HttpContext.Current.Request.Form.Get(), but I'm not sure if I really want to be doing that in the Owin pipeline.
I know I can use .ReadFormAsync() to get an IFormCollection, which appears to work fine for standard submits, but with a multi-part/form-data post the boundary value, content type, and variable name are all getting rolled into the key. So I can't just do formVars.Get("VariableName"), because it's not the variable name, it's a composite. Seems like it shouldn't be doing that though... right?
public AppFunc PreAuthMiddleware(AppFunc next) {
AppFunc appFunc = async (IDictionary<string, object> environment) => {
IOwinContext context = new OwinContext(environment);
IFormCollection formVars = await context.Request.ReadFormAsync();
... Now What ...
await next.Invoke(environment);
};
return appFunc;
}
I was hoping that accessing form variables and file data would be as easy as it was with HttpContext, but it seems there may be more work to be done.
If anyone has any insight on this, please let me know. Otherwise I'll probably just end up hacking the key names together if I see the main content-type is multi-part/form-data.

How do I use findOrCreateEach in waterline/sailsjs?

I been looking around on the sails site and was lead to the waterline page. I am curious to how I can use the findOrCreateEach method. Specifically, number of arguments, what it will return, and how it will benefit me using it? I been searching, around and going to have to dive into the source code. I figure I ask here while I look.
Method without bluebird promises
Model.findOrCreateEach(/* What Goes Here */).exec(/* What Returns Here */);
With bluebird promises
Model.findOrCreateEach(/* What Goes Here */).then(/* What Returns Here */);
findOrCreateEach is deprecated; that's why it's not in the documentation. The best way to replicate the functionality is by using .findOrCreate() in an asynchronous loop, for example with async.map:
// Example: find or create users with certain names
var names = ["scott", "mike", "cody"];
async.map(names, function(name, cb) {
// If there is a user with the specified name, return it,
// otherwise create one
User.findOrCreate({name: name}, {name: name}).exec(cb);
},
function done(err, users) {
if (err) { <handle error and return> }
<users now contains User instances with the specified names>
});

CodeIgniter: URIs and Forms

I'm implementing a search box using CodeIgniter, but I'm not sure about how I should pass the search parameters through. I have three parameters: the search string; product category; and the sort order. They're all optional. Currently, I'm sending the parameters through $_POST to a temporary method, which forwards the parameters to the regular URI form. This works fine. I'm using a weird URI format though:
http://site.com/products/search=computer,sort=price,cat=laptop
Does anyone have a better/cleaner format of passing stuff through?
I was thinking of passing it into the products method as arguments, but since the parameters are optional things would get messy. Should I suck it up, and just turn $_GET methods on? Thanks in advance!
Query Strings
You can enable query strings in CodeIgniter to allow a more standard search function.
Config.php
$config['enable_query_strings'] = FALSE;
Once enabled, you can accept the following in your app:
http://site.com/products/search?term=computer&sort=price&cat=laptop
The benefit here is that the user will find it easy to edit the URL to make a quick change to their search, and your search uses common search functionality.
The down side of this approach is that you are going against one of the design decisions of the CodeIgniter development team. However, my personal opinion is that this is OK provided that query strings are not used for the bulk of your content, only for special cases such as search queries.
A much better approach, and the method the CI developers intended, is to add all your search parameters to the URI instead of a query string like so:
http://site.com/products/search/term/computer/sort/price/cat/laptop
You would then parse all the URI segments from the 3rd segment ("term") forward into an array of key => value pairs with the uri_to_assoc($segment) function from the URI Class.
Class Products extends Controller {
...
// From your code I assume you are calling a search method.
function search()
{
// Get search parameters from URI.
// URI Class is initialized by the system automatically.
$data->search_params = $this->uri->uri_to_assoc(3);
...
}
...
}
This would give you easy access to all the search parameters and they could be in any order in the URI, just like a traditional query string.
$data->search_params would now contain an array of your URI segments:
Array
(
[term] => computer
[sort] => price
[cat] => laptop
)
Read more about the URI Class here: http://codeigniter.com/user_guide/libraries/uri.html
If you're using a fixed number of parameters, you can assign a default value to them and send it instead of not sending the parameter at all. For instance
http://site.com/products/search/all/somevalue/all
Next, in the controller you can ignore the parameter if (parameter == 'all'.)
Class Products extends Controller {
...
// From your code I assume that this your structure.
function index ($search = 'all', $sort = 'price', $cat = 'all')
{
if ('all' == $search)
{
// don't use this parameter
}
// or
if ('all' != $cat)
{
// use this parameter
}
...
}
...
}