get attribute from selectNodes in JavaScript and XML? - javascript

I am trying to get an attribute from an XML node from JavaScript.
item.selectNodes("enclosure[#url]")
That is not working like I thought it would :(
Any hints ?
thanks!

[#url]
is a predicate, which does not select the attribute but filters the "enclosure" nodes that do have a url attribute.
In XPath,
enclosure/#url
would select the attribute.

This:
item.selectNodes("enclosure[#url]")
will give you a collection of enclosure nodes that have a url attribute.
To get a collection of url attribute nodes that are on enclosure nodes, do this:
item.selectNodes("enclosure/#url")
Which you must then loop over to get the values of each one. Remember this gives you attribute nodes, not attribute values. You can use attributeNode.nodeValue to get the value from the node.
If you are expecting just one such node, then use selectSingleNode instead of selectNodes. This will give you the first matching node, instead of a collection of all matching nodes.

Related

Select an object property within an attribute of the DOM

I looked at this thread but it didn't help: Find an element in DOM based on an attribute value
I need a Vanilla JS solution to select a username that is in a custom attribute of an <a> tag in the DOM. I used const users = document.querySelectorAll('a[metadata]') which returns a NodeList of all the <a> tags with all their attributes. If I type console.log(users[0]), I get:
<a href="#" class="btn-normal" metadata="
{
'username':'johnny134',
'category':'shoes',
'summary':'Just a guy called Johnny',
'userId':1223432432
}"
</a>
To access the username, I have tried const usernames = document.querySelectorAll('a[metadata="username"]'); but just get back undefined. I think my issue is that username is in an object and I can't figure out how to select it.
Thanks in advance
First, note that document.querySelectorAll returns a list of elements that match the given query, not a list of the values of attributes of those elements that you specify in the query.
From const users = document.querySelectorAll('a[metadata]'), you can get the metadata attribute of, say, the first element, like so:
const metadata0 = users[0].getAttribute("metadata");
And then, since it's a JSON string, you parse it:
const user0 = JSON.parse(metadata0);
Now you can use user0 like a regular JavaScript object:
user0.username
// johnny134
P.S. The JSON in the metadata attribute is not valid, and you may get an error when you try to parse it. Use double quotes in JSON, not single quotes.

How can I loop through nested html elements and replace an id number with another id?

We have a piece of html that we are using to create an object that we pass into a function that clones data.
We are trying to get that cloned data and replace a common id with a new id that has been dynamically set elsewhere. below is what we have got:
// This is the cloned data we have got
var data = this.$container.find('.fields').clone();
// This is the id we are getting to find in the cloned html above
var id = this.$container.data('id');
// This is where we need to go through all html and replace the id above in here with whatever we need
var replacedHtml = data.innerHtml().replace(id,'test');
// the cloneVariant function takes the data and does some good stuff with it. The $.parseHTML(replacedHtml) takes the string html and makes the dom element that goes into the coneVariant function.
this.matrix.cloneVariant(this.$container,$.parseHTML(t));
What I need to do is replace that found id in the html with a string.
Can this be done?
You can use the [id] selector to find any element in the $container which has an id attribute, then provide a function to prop() to update. You need to do the latter to ensure that the id attributes remain unique, and that you don't duplicate them at all.
data.find('[id]').prop(id, function(i, id) {
return id + '_' + i
});
It is worth noting, though, that having incremental id attributes, and dynamically generating id attributes at runtime is a bit of a code smell. It's generally a better idea to use common classes and then relate elements to each other using DOM traversal.

SAPUI5 bindAggregation from XML Model by Attribute Name

I do have a XML-Model which looks like this:
I would like to add the sap.m.ComboBox control to my UI. I want the value from attribute Name from the Member tag. I am able to do so with this code:
new sap.m.ComboBox({
items : {
templateShareable : true,
path : "metadata>/edmx:DataServices/edm:Schema/edm:EnumType/0/edm:Member",
template : new sap.ui.core.ListItem({
text: "{metadata>#Name}"
})
}
})
BUT, instead of selecting the EnumType hard by calling it's index (edm:EnumType/0/), I would rather like to select it by it's attribute Name. E.g. something like this would be nice:
"metadata>/edmx:DataServices/edm:Schema/edm:EnumType(Name=RoleCategory)/edm:Member"
Does anyone know how to do so? Any idea is highly appreciated.
There is no such thing in the path syntax. You can see in the OpenUI5 code that the path supports only
attributes #
text()
elements by tag name
array indices.
You cannot use element binding to filter either as element binding does not support filtering and sorting.
You could however attach to the models requestCompleted or metadataLoaded events and update the binding path or copy the data to a separate model.
If you want it dirty you could use a container control, bind it to /edmx:DataServices/edm:Schema/edm:EnumType with your ComboBox as template and apply an appropiate filter. You then have to use a relative path in you Combobox. :)

Identity selectors in jQuery returning arrays

Suppose I have a div tag like this:
<div id="group-dialog" class="modal-dialog">
Now I want to grab it as a jQuery object (in this case so I can run .dialog()).
When I try this:
var gDialog = $('#group-dialog');
I get an array back (!!).
Why am I getting an array? Isn't the point of having an ID attribute that there's only one? I can see getting multiple p's or .my-css-thing back ...
Next question:
I have this array with 1 object in it that I now want to access as a jQuery object.
When I do this:
$(gDialog[0])
And pull it up in F12, I still have an array!! I thought I de-referenced the array already by picking the first element.
This doesn't seem to help either:
var gDialog = $('#group-dialog:first');
This is basic, but I run into this problem a lot. It seems like it used to be a lot simpler!
What is the best way to access this DOM element as a jQuery object?
Answer 1
jQuery selectors always return arrays.
Selection with id attribute is a particular use case and ideally the result should be unique. However, there is nothing preventing you from having duplicated ids in a HTML document (although this is bad practice).
Answer 2
The following code will get you the first element as a DOM object:
var gDialog = $('#group-dialog')[0];
Note: you may want to check the size of the return array first.
As far as I know, there is no way to transform this DOM element back to a jQuery object. The standard use case would be to directly used $('#group-dialog') and asume that it is found and unique.
Try using .get(). Though I'm not sure it will work with dialog()
Retrieve the DOM elements matched by the jQuery object.
var gDialog = $('#group-dialog').get();
If you're trying to grab it to use it on a dialog, you can just put
$(document).ready(function(){
$('#group-dialog').dialog({put options here})
});

How to get string representation of HTML element

Is there any way to get easily string representation of node without its content? I mean - element.outerHTML returns string representation of element AND its content. I'd like to get something like element.outerHTML without element.innerHTML.
I want to make fallback of dirxml for consoles without support, using console.group and console.groupEnd
element.cloneNode(false).outerHTML
.cloneNode(false) creates a duplicate node with identical attributes, but not the child nodes, and .outerHTML returns its serialization that matches the original node excluding the node's content.

Categories