parse XML attribute value using javascript - javascript

How do I get the first url value in the 'media:content'.
Here is my XML format
<root>
<item>
<title>title1</title>
<media:group>
<media:content url="http://delivery_sva/1kqoy0pabup891733zq15sm2t3.mp4" />
<media:content url="http://delivery_sva/1kqoy0pabup891733zq15sm2t3.mp3" />
</media:group>
</item>
<item>
<title>title2</title>
<media:group>
<media:content url="http://delivery_sva/1kqoy0pabup891733zq15sm2t3.mp4" />
<media:content url="http://delivery_sva/1kqoy0pabup891733zq15sm2t3.mp3" />
</media:group>
</item>
</root>
I tried with the following code, but I am not able to getting the value of the attribute.
var doc = this.responseXML.documentElement;
var items = doc.getElementsByTagName("item");
for (var c = 0; c < items.length; c++) {
var item = items.item(c);
var sTitle1 = item.getElementsByTagName("title").item(0).text;
var itemswebportal = item.getElementsByTagName("media:content");
//currentwindow.sTitle1 is getting from the previous screen
if (sTitle1 == currentwindow.sTitle1) {
alert(itemswebportal[1].getAttribute("url"));
}
}

The problem is the : in the media:content. Try escaping it with two \. But I recommend using jquery for simpler manipulation and consistency across browsers.
Check the fiddle.

Related

Replace time value inside a programming code using Excel VBA or Javascript

I am trying to make scrolling karaoke lyrics of a song. The lyric software outputs a code which contains time in seconds that I need to convert.
I Have two versions of the same song. One runs in 52 bpm (beats per minute) which is a slower version and another runs at 104 bpm which is faster version.
I have completed the first version which took hell lot of a time. I want to convert the code in such a way that I can get the faster version automatically.
Here is the sample code
<item dStartTime="4" dEndTime="8" n3DRhythm="2" str3DSceneLayoutFile="">
<text>Batti Gul Meter Chalu</text>
</item>
<item dStartTime="9.52" dEndTime="14.47" n3DRhythm="2" str3DSceneLayoutFile="">
<text>rajj<10.44> ke<10.99> rulaya</text>
</item>
<item dStartTime="14.47" dEndTime="19.06" n3DRhythm="2" str3DSceneLayoutFile="">
<text>rajj ke<15.94> hansaya</text>
</item>
I want to convert the same code as shown below where the time in seconds should be exactly half with two decimal points
<item dStartTime="2" dEndTime="4" n3DRhythm="2" str3DSceneLayoutFile="">
<text>Batti Gul Meter Chalu</text>
</item>
<item dStartTime="4.76" dEndTime="7.24" n3DRhythm="2" str3DSceneLayoutFile="">
<text>rajj<5.22> ke<5.50> rulaya</text>
</item>
<item dStartTime="7.24" dEndTime="9.53" n3DRhythm="2" str3DSceneLayoutFile="">
<text>rajj ke<7.97> hansaya</text>
</item>
I took the code in MS Excel and tried using substitute, concatenate and other few formulas to achieve what I need but I am unable to do so and though excel vba can help but I cannot do it in vba. Request you guys to help me out in this as I need to convert a lot of songs. Your kind assistance will save a lot of time. Any help in excel vba, javascript or any other way to replace the code.
In the <item> section, I need to convert the dStartTime and dEndTime
In the <text> section, I need to convert anything that looks like a number
Thank you
In Javascript, you can use DOMParser to convert the string into a document, after which you can iterate over each <item>, change the dStartTime and dEndTime attributes, and then change any numbers in the child <text> node:
const str = `<item dStartTime="4" dEndTime="8" n3DRhythm="2" str3DSceneLayoutFile="">
<text>Batti Gul Meter Chalu</text>
</item>
<item dStartTime="9.52" dEndTime="14.47" n3DRhythm="2" str3DSceneLayoutFile="">
<text>rajj<10.44> ke<10.99> rulaya</text>
</item>
<item dStartTime="14.47" dEndTime="19.06" n3DRhythm="2" str3DSceneLayoutFile="">
<text>rajj ke<15.94> hansaya</text>
</item> `;
const doc = new DOMParser().parseFromString(str, 'text/html');
const halve = num => Math.round(100 * num / 2) / 100;
const halveAttrib = (node, name) => {
const newVal = halve(node.getAttribute(name))
node.setAttribute(name, newVal);
};
doc.querySelectorAll('item').forEach((item) => {
halveAttrib(item, 'dStartTime');
halveAttrib(item, 'dEndTime');
item.children[0].textContent = item.children[0].textContent
.replace(/\d+(\.\d+)/g, num => halve(num).toFixed(2));
});
const output = doc.body.innerHTML
.replace(/dstarttime/g, 'dStartTime')
.replace(/dendtime/g, 'dEndTime')
.replace(/n3drhythm/g, 'n3DRhythm')
.replace(/str3dscenelayoutfile/g, 'str3DSceneLayoutFile');
console.log(output);
This uses a DOM parser to write out the values and duration after reading each section of HTML from an html file. I struggled with accessing the Text nodes so have had to hack my way around that which I am not best pleased with. It does mean you know the value you are searching for which means you can do a replace on the html string by using regex .Replace method. For dStartTime and dendTime you can do a straight replace on the outerHTML. This replace just in the current HTMLDocument unless you write back out to file. SetAttribute doesn't work in this instance. I am not sure why I couldn't access the text nodes, particularly as don't have source HTMLDocument. Would be good to see if someone can solve that.
item.outerHTML = Replace$(item.outerHTML, "dstarttime=" & Chr$(34) & item.dstarttime & Chr$(34), "dstarttime=" & 666 & Chr$(34)) 'example 666 as replace value.
vba:
Option Explicit
Public Sub GetValues()
'VBE > Tools > References > HTML Object Library
Dim html As HTMLDocument
Debug.Print "doc1", vbNewLine
Set html = GetHTMLFileContent("C:\Users\User\Desktop\test.html") 'first html document. Info saved in text file with .html extension
GetItems html
Debug.Print "doc2", vbNewLine
Set html = GetHTMLFileContent("C:\Users\User\Desktop\test2.html") 'second html document. Info saved in text file with .html extension
GetItems html
End Sub
Public Sub GetItems(ByVal html As HTMLDocument)
Dim items As Object, item As Object, counter As Long
Set items = html.getElementsByTagName("item")
For Each item In items
Debug.Print " item " & counter + 1
Dim itemArr() As String
itemArr = Split(html.body.innerHTML, "</ITEM")
Debug.Print "startTime = " & Round(item.dStartTime, 2), "endTime = " & Round(item.dendTime, 2), "duration : " & Round(item.dendTime - item.dStartTime, 2)
Debug.Print "Associated text numbers "
On Error Resume Next
GetTextAttributeNumbers Split(itemArr(counter), "<TEXT>")(1)
On Error GoTo 0
counter = counter + 1
Next item
End Sub
Public Sub GetTextAttributeNumbers(ByVal inputString As String)
Dim matches As Object, iMatch As Object
With CreateObject("vbscript.regexp")
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = "\d{1,}(\.\d+)?"
If .TEST(inputString) Then
Set matches = .Execute(inputString)
For Each iMatch In matches
Debug.Print iMatch
Next iMatch
End If
End With
End Sub
Public Function GetHTMLFileContent(ByVal filePath As String) As HTMLDocument
'"C:\Users\HarrisQ\Desktop\test.html"
Dim fso As Object, hFile As Object, hString As String, html As New HTMLDocument
Set fso = CreateObject("Scripting.FileSystemObject")
Set hFile = fso.OpenTextFile(filePath)
Do Until hFile.AtEndOfStream
hString = hFile.ReadAll()
Loop
html.body.innerHTML = hString
Set GetHTMLFileContent = html
End Function
To properly parse the documents the following syntax is required:
Doc1
<html>
<head></head>
<body>
<item dstarttime="4" dendtime="8" n3drhythm="2" str3dscenelayoutfile="">
<text>
Batti Gul Meter Chalu
</text>
</item>
<item dstarttime="9.52" dendtime="14.47" n3drhythm="2" str3dscenelayoutfile="">
<text>
rajj<10.44> ke<10.99> rulaya
</text>
</item>
<item dstarttime="14.47" dendtime="19.06" n3drhythm="2" str3dscenelayoutfile="">
<text>
rajj ke<15.94> hansaya
</text>
</item>
</body>
</html>
Doc2
<html>
<head></head>
<body>
<item dstarttime="2" dendtime="4" n3drhythm="2" str3dscenelayoutfile="">
<text>
Batti Gul Meter Chalu
</text>
</item>
<item dstarttime="4.76" dendtime="7.24" n3drhythm="2" str3dscenelayoutfile="">
<text>
rajj<5.22> ke<5.50> rulaya
</text>
</item>
<item dstarttime="7.24" dendtime="9.53" n3drhythm="2" str3dscenelayoutfile="">
<text>
rajj ke<7.97> hansaya
</text>
</item>
</body>
</html>
This means, if not present, concantentating the missing start and end strings.
"<html><head></head><body>" & yourHTMLString & "</body>
</html>"
Example output from second document:

How to find specific location of attribute in xml node

I have been trying to find the location of an attribute (line, column) in a specific xml node. I know i can reach the node and the attribute value by using XPATH or sax parser but havent found a way to locate the position of the attribute.
Appreciate your help
The DOM parsers found in browsers typically don't make any location information available (AFAIK). If you're using a third-party SAX parser then you may be more lucky; but it all depends on the parser you are using. I'd be surprised to see location information at the individual attribute level, though: it's expensive to provide, and element-level information is more common.
I managed to do this using XMLDOM.
DOMParser = require('xmldom').DOMParser;
var parser = new DOMParser({locator:{}});
var content = parser.parseFromString(xmlContent, "text/xml");
var rootNode = this.parseXml(content.documentElement);
var attrs = rootNode .attributes || [];
for (var i = 0; i < attrs.length; i++) {
var attr = attrs[i];
var nColumn = attr.columnNumber;
var nLine = attr.lineNumber;
}
For example, a sample XML file is:
<parents name='Parents'>
<Parent id='1' name='Parent_1'>
<Children name='Children'>
<child name='Child_2' id='2'>child2_Parent_1</child>
<child name='Child_4' id='4'>child4_Parent_1</child>
<child name='Child_1' id='3'>child1_Parent_1</child>
<child name='Child_3' id='1'>child3_Parent_1</child>
</Children>
</Parent>
<Parent id='2' name='Parent_2'>
<Children name='Children'>
<child name='Child_1' id='8'>child1_parent2</child>
<child name='Child_2' id='7'>child2_parent2</child>
<child name='Child_4' id='6'>child4_parent2</child>
<child name='Child_3' id='5'>child3_parent2</child>
</Children>
</Parent>
</parents>
Using XPath, you can do :
//Parent[#id='1']/Children/child/#name
Output :
Child_2
Child_4
Child_1
Child_3

Reading xml using jquery or javascript

My xml looks like this, I am able to retrieve the items and get the data from nodes like <title>, <description>. How to get the values from <media:title> and <media:credit>, <media:thumbnail>
This is how am able to get the data
var xmlparser = new DOMParser();
var xmlData = xmlparser.parseFromString(data.text(), "text/xml");
var items = xmlData.getElementsByTagName('item');
for(var i = 0; i < items.length; i++){
var title = items[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
var desc = items[i].getElementsByTagName("description")[0].childNodes[0].nodeValue;
}
<pre xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<Channel>
<item>
<title>List of records</title>
<description>reading xml</description.
<media:title xmlns:media="http://search.yahoo.com/mrss/">
SinkorSwim Trailer
</media:title>
<title>Sink or Swim - Trailer</title>
<description>Jon Bowermaster's documentary</description>
<media:description xmlns:media="http://search.yahoo.com/mrss/">
Jon Bowermaster's documentary on a learn-to-swim camp
</media:description>
<media:credit xmlns:media="http://search.yahoo.com/mrss/" role="Director"
scheme="urn:ebu">
Jon Bowermaster
</media:credit>
<media:status xmlns:media="http://search.yahoo.com/mrss/" state="active"/>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/"
type="landscape" url="http://snagfilms-video.jpg"/>
<media:player xmlns:media="http://search.yahoo.com/mrss/" height="323"
url="http://embed.snagfilms.com/embed/player?filmId=00000158-b20c-d8f9-
affd-b32ce8700000" width="500"/>
</item>
<item></item>
<item></item>
</channel>
</pre>
The media in media:title denotes an XML namespace prefix. The namespace prefix is only a shortcut for the namespace. The namespace has to be defined somewhere in the document with an xmlns:media attribute.
Then you can use the namespace aware getElementsByTagNameNS() function to query for the title element:
console.log(xml.getElementsByTagNameNS('xmlns:media="http://search.yahoo.com/mrss/"', 'title'));
first parameter you have to pass the namespace name and not the prefix.

extract value from XML in pure JavaScript

I am fetching an XML response from an external tool using
var myXML = api.path("item/"+itemId+"/metadata").dataType("xml").get();
The XML structure I receive this way looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MetadataListDocument xmlns="http://xml.vidispine.com/schema/vidispine">
<item id="VX-3594">
<metadata>
<revision>VX-61522,VX-61520,VX-61519,VX-61515,VX-61513,VX-61514,VX-61525,VX-61523</revision>
<group>Final Cut Server</group>
<timespan start="-INF" end="+INF">
<field uuid="2913190d-635c-4f81-951c-4ff3f934a547" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">
<name>shapeTag</name>
<value uuid="2c8b57d0-5c47-49c9-a4f0-54f7fef803cc" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">lowres</value>
<value uuid="6d994b0c-9d91-4b32-8052-824b3467a29e" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">original</value>
<value uuid="85cd07b7-6f13-4f6c-86fa-e42db20860c0" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">house_format_audio_through</value>
</field>
<field uuid="e2b4ca3c-6765-4890-99f4-f6e0624099eb" user="admin" timestamp="2015-03-16T16:47:57.506+01:00" change="VX-61513">
<name>portal_mf129489</name>
<value uuid="ab60ed17-75f4-4593-b068-9d8b6a700025" user="admin" timestamp="2015-03-16T16:47:57.506+01:00" change="VX-61513">no</value>
</field>
</timespan>
</metadata>
</item>
</MetadataListDocument>
Now I need to extract the value of the field with the name portal_mf129489, which in this case would be no.
To extract data from the xml output I already set the default name space:
default xml namespace = "http://xml.vidispine.com/schema/vidispine";
and I can extract things using
var myTimespan = myXML.item.metadata.timespan;
My question though is, how can I find a field element, which has a child element named portal_mf129489? If I find this element, I would need to fetch the value of the field's child element named value.
Each XML has multiple field elements, and inside the field I am looking for, name is always the first child element, value is always the second element.
Any ideas?
You can do this with little help of jQuery. The idea is to use jQuery to query XML document:
var xml = $.parseXML('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><MetadataListDocument xmlns="http://xml.vidispine.com/schema/vidispine"><item id="VX-3594"><metadata><revision>VX-61522,VX-61520,VX-61519,VX-61515,VX-61513,VX-61514,VX-61525,VX-61523</revision><group>Final Cut Server</group><timespan start="-INF" end="+INF"><field uuid="2913190d-635c-4f81-951c-4ff3f934a547" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523"><name>shapeTag</name><value uuid="2c8b57d0-5c47-49c9-a4f0-54f7fef803cc" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">lowres</value><value uuid="6d994b0c-9d91-4b32-8052-824b3467a29e" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">original</value><value uuid="85cd07b7-6f13-4f6c-86fa-e42db20860c0" user="system" timestamp="2015-03-16T16:52:48.061+01:00" change="VX-61523">house_format_audio_through</value></field><field uuid="e2b4ca3c-6765-4890-99f4-f6e0624099eb" user="admin" timestamp="2015-03-16T16:47:57.506+01:00" change="VX-61513"><name>portal_mf129489</name><value uuid="ab60ed17-75f4-4593-b068-9d8b6a700025" user="admin" timestamp="2015-03-16T16:47:57.506+01:00" change="VX-61513">no</value></field></timespan></metadata></item></MetadataListDocument>');
var value = $(xml).find('field > name').filter(function(){ return $(this).text() === 'portal_mf129489' }).siblings('value').text();
$('body').append(value);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Okay, got it working, now. I added the function:
function getField(ts, name) {
for (var i = 0; i < ts.field.length(); i++) {
var f = ts.field[i];
if (f.name == name) {
return f;
}
}
}
and this:
var r = api.path("item/"+itemId+"/metadata").dataType("xml").get();
var metadata = r.item[0].metadata;
var ts = metadata.timespan[0];
var tag = getField(ts, 'portal_mf129489');
if (tag && tag.value) {
logger.log('value: '+tag.value[0]);
}

how to Convert a var to xml content using jquery

I am currently working with Jquery and my entire project needs to be done only using sharepoint Client Object Model (so i cant make use of server side coding). I have created a xml structure (by appending some string together) and stored it in a jquery var variable. Now my variable content looks like this
<Collection xmlns="http://schemas.microsoft.com/collection/metadata/2009"
xmlns:ui="http://schemas.microsoft.com/livelabs/pivot/collection/2009"
SchemaVersion="1" Name="listname">
<FacetCategories>
<FacetCategory Name="Title" Type="String" />
<FacetCategory Name="Created By" Type="String" />
<FacetCategory Name="Modified By" Type="String" />
</FacetCategories>
<Items ImgBase="http://460d87.dzc">
<Item Id="0" Img="#0" Name="Name1" Href="http://site/1_.000">
<Facets>
<Facet Name="Title">
<String Value="Name1" />
</Facet>
</Facets>
</Item>
</Items>
</collection>
I want to convert this variable in to xml content purely based on jquery.I have used ParseXml() Method but i'm not able to see the output in alert(). Please help me out with this.
Just use native built-in XML parser:
var parser, xml;
if (window.DOMParser) {
parser = new DOMParser();
xml = parser.parseFromString(str, "text/xml");
}
else { // IE
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = "false";
xml.loadXML(str);
}
var nodes = xml.getElementsByTagName('FacetCategory');
var i, l = nodes.length, items = [];
for (i = 0; i < l; i++) {
console.log(nodes[i].getAttribute('Name'));
}
http://jsfiddle.net/QqtMa/
Your xml is invalid, your root element is Collection but the closing tag is collection with small c, so the parser is failing

Categories