4

I have the fallowing string:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 18"><title>A</title><path d="M0,18V4A3.83,3.83,0,0,1,1.19,1.18,3.85,3.85,0,0,1,4,0H8a3.81,3.81,0,0,1,2.8,1.19A3.85,3.85,0,0,1,12,4V18H8V10H4v8ZM4,8H8V4A2,2,0,0,0,6,2a1.92,1.92,0,0,0-1.4.59A1.92,1.92,0,0,0,4,4Z"/></svg>

I would like to retrieve value from view box:

"0 0 12 18"

What I have so far:

/"\d\s\d\s\d\d\s\d\d"/

As you can see this does not guarantee that extracted value will be viewBox, plus it does not cover situation when values are not single digit, like so: 123 32 1239 33

Nikola Mitic
  • 1,298
  • 3
  • 11
  • 23
  • 3
    [H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags) - don't use regex, use a parser – ctwheels Jan 19 '18 at 20:54
  • @Jan that was way too fast of a response to my comment... – ctwheels Jan 19 '18 at 20:55
  • 1
    @ctwheels: Honestly I stopped reading a regex question starting with `<...`. I did wait for the pony link by you, though :) – Jan Jan 19 '18 at 20:57
  • Thanks but I need to be lib free – Nikola Mitic Jan 19 '18 at 20:57
  • @jan Yeah man! Thanks. – Nikola Mitic Jan 19 '18 at 20:58

3 Answers3

5

You could use https://developer.mozilla.org/en-US/docs/Web/API/DOMParser since it's not wise to use RegExp on XML / HTML

const myString = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 18"><title>A</title><path d="M0,18V4A3.83,3.83,0,0,1,1.19,1.18,3.85,3.85,0,0,1,4,0H8a3.81,3.81,0,0,1,2.8,1.19A3.85,3.85,0,0,1,12,4V18H8V10H4v8ZM4,8H8V4A2,2,0,0,0,6,2a1.92,1.92,0,0,0-1.4.59A1.92,1.92,0,0,0,4,4Z"/></svg>`;

const parser = new DOMParser();
const doc = parser.parseFromString(myString, "text/html");

console.log( doc.querySelector("svg").getAttribute("viewBox") ); // "0 0 12 18"

The Why not use RegExp to parse? can be illustrated by the simple fact that DOM is extremely permissive, attributes (i.e: like data-*) are not restrictive on it's content (just think of i.e: data-cont="<b data-cont='<b'></b>"), etc etc... imagine the unsustainable regex nightmare you should write. And you'd never get it right.

Regex ...for the "I know my string, man!" moments:

const myString = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 18"><title>A</title><path d="M0,18V4A3.83,3.83,0,0,1,1.19,1.18,3.85,3.85,0,0,1,4,0H8a3.81,3.81,0,0,1,2.8,1.19A3.85,3.85,0,0,1,12,4V18H8V10H4v8ZM4,8H8V4A2,2,0,0,0,6,2a1.92,1.92,0,0,0-1.4.59A1.92,1.92,0,0,0,4,4Z"/></svg>`;

const viewBox = (/viewBox="([^"]+)"/.exec(myString)||'')[1] ;
console.log( viewBox )  // "0 0 12 18" or undefined (if not found)
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • 1
    Fair point on why not to use regex for html/xml parse. I will make this one accepted for the sake of the rest of the community, but as @Jan mentioned it is also ok to use regex for small "htm/xml/svg" chunks such as mine, because I'm sure that I will get this data and nothing else, since program I'm writing depend on such structure. – Nikola Mitic Jan 19 '18 at 21:22
  • This has been a discussion for ages and it won't stop anywhere soon. I did vote for your approach as well but honestly, attributes like `data-cont="viewBox=..."` are very rare in reality. – Jan Jan 19 '18 at 21:23
1

Of course, you can analyze short and simple XML/HTML/SVG sequences with regular expressions. In your case this could be

viewBox="([^"]+)"

See a demo on regex101.com and the following snippet:

var svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 18"><title>A</title><path d="M0,18V4A3.83,3.83,0,0,1,1.19,1.18,3.85,3.85,0,0,1,4,0H8a3.81,3.81,0,0,1,2.8,1.19A3.85,3.85,0,0,1,12,4V18H8V10H4v8ZM4,8H8V4A2,2,0,0,0,6,2a1.92,1.92,0,0,0-1.4.59A1.92,1.92,0,0,0,4,4Z"/></svg>'

var match = svg.match(/viewBox="([^"]+)"/)
console.log(match[1])

However, it is not advisable...

Jan
  • 42,290
  • 8
  • 54
  • 79
  • Why wouldn't be advisable? And would using DOMParser make things faster? And thx btw. – Nikola Mitic Jan 19 '18 at 21:02
  • @NikolaMitic: No, a regex is usually faster but a parser is safer. – Jan Jan 19 '18 at 21:03
  • 1
    @NikolaMitic please click on the link I posted in the comments. HTML is not regular language (which is why Jan mentions it's *not advisable*). – ctwheels Jan 19 '18 at 21:03
  • @ctwheels: Despite being very popular, unfortunately, the answer you linked to, does not explain very much as to **why** you shouldn't do it. – Jan Jan 19 '18 at 21:04
  • Fair enough, @NikolaMitic see [Using regular expressions to parse HTML: why not?](https://stackoverflow.com/questions/590747/using-regular-expressions-to-parse-html-why-not) – ctwheels Jan 19 '18 at 21:06
  • @ctwheels: Imo, this is a more realistic view - https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1733489#1733489 – Jan Jan 19 '18 at 21:07
  • @all thanks, just had a look at it while you guys had discussion here. The thing is that I'm sure that my svgs are going to be small ones, just like at that url answer Jan posted. Regex would be faster solution and with not having much to parse,I think it is safe to go with regex here, your final thoughts, before I choose accepted answer? :D – Nikola Mitic Jan 19 '18 at 21:11
  • @NikolaMitic: In this case, a regular expression solution might very well work - though Roko's answer feels more like the "right approach". – Jan Jan 19 '18 at 21:14
  • @Jan all right, I agree. I will choose his one (for the sake of the rest of the community), but will go with regex for my case, but also gonna post comment on his answer referring to use of regex , thank you. – Nikola Mitic Jan 19 '18 at 21:18
1

Just use getAttribute and split by whitespaces or comma. According to MDN, it could be whitespaces or comma that separates the values. https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox

    let svg_canvas = document.getElementById('svg_canvas');
    let viewBox = svg_canvas.getAttribute('viewBox');
    let view_box_attr = viewBox.split(' '); //whitespace or comma

    //min-x, min-y, width and height
    //the values are string so need to parse
    let zoom_factor = 1;
    let minx = parseInt(view_box_attr[0]) + zoom_factor;
    let miny = parseInt(view_box_attr[1]) + zoom_factor;
    let width = parseInt(view_box_attr[2])- zoom_factor;
    let height = parseInt(view_box_attr[3]) - zoom_factor;
    let newViewBox =  minx+" "+miny+" "+width+" "+height;
    console.log('old '+viewBox+' new '+newViewBox);
    svg_canvas.setAttribute( 'viewBox', newViewBox);
Omar Khan
  • 141
  • 3