Home > database >  Get DOM element by custom attribute value inside SVG
Get DOM element by custom attribute value inside SVG

Time:01-21

Having this sample SVG (which gets created in Microsoft Visio):


<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
        xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="34.6243in" height="10.4874in"
        viewBox="0 0 2492.95 755.093" xml:space="preserve" color-interpolation-filters="sRGB" >

<g id="shape1014-243" v:mID="1014" v:groupContext="shape" transform="translate(30.3431,-54.0037)">
            <title>Team frame.1171</title>
            <desc>Test</desc>
            <v:custProps>
                <v:cp v:nameU="Theme" v:lbl="MY_UNIQUE_ID_1" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false"
                        v:ask="false" v:langID="0" v:cal="0" v:val="VT0(0):26"/>
            </v:custProps>
            <v:textBlock v:margins="rect(0,0,0,0)" v:tabSpace="42.5197"/>
            <v:textRect cx="100.34" cy="791.095" width="200.69" height="72.0035"/>
            <path d="M56.21 84.35 L55.85 84.35 L17.01 84.35 A17.0079 17.0079 -180 0 0 0 101.35 L0 738.09 A17.0079 17.0079 -180 0
                         0 17.01 755.09 L183.67 755.09 A17.0079 17.0079 -180 0 0 200.68 738.09 L200.68 101.35 A17.0079 17.0079 -180
                         0 0 183.67 84.35 L144.83 84.35" />
            <text x="5.13" y="809.09"  v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Arrivals</text>       
</g>
</svg>

I want to access the 'g' element. The problem is I can't simply use document.getElementById("shape1014-243"); as the ID will be randomly generated by Visio.

The value which I know I can access it by, is this value v:lbl="MY_UNIQUE_ID_1". Now, how can I access the 'g' element knowing only that value?

I can do the following:

  1. Get all v:cp elements with var elements = document.getElementsByTagName("v:cp");
  2. Loop through them and check if elements[X].getAttribute("v:lbl") === "MY_UNIQUE_ID_1"
  3. If true, then get the 'g' element using element[X].parentElement.parentElement

But is there a better way? I tried document.querySelector('[v:lbl="MY_UNIQUE_ID_1"]'); but it returns error 'not a valid selector'.

I tried the code in the question. I am expecting a solution

CodePudding user response:

I would probably start with searching for the element you actually know :

let elem = document.querySelector(`*[v\\:lbl="MY_UNIQUE_ID_1"]`);

(note the \\ escaping the colon)

Then use this and loop on elem.parentElement then its parent element and so on until I find one that has nodeName as g. (Unfortunately CSS does not have a way to select an element that contains another specific element -- that I know of at least)

This works:

let elem = document.querySelector(`*[v\\:lbl="MY_UNIQUE_ID_1"]`);
while(elem != null && elem.nodeName != `g`){
    elem = elem.parentNode;
}
if(elem !== null){
    // do something with elem
}

CodePudding user response:

Streamlining what you already proved to work:

Find the element by your known, unique label get the closest g element ( parentElement.parentElement )

the example below will log the id of the g element, so shows "shape1014-243"

function getG( uniqueLabel ){
  var elementOne = document.querySelector(`v\\:cp[v\\:lbl='${uniqueLabel}']`);
  return elementOne.closest('g');
}

function logGetG( uniqueLabel ){
  console.log(getG(uniqueLabel).id);
}
<button onClick='logGetG("MY_UNIQUE_ID_1");'>Get G!</button>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
        xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="34.6243in" height="10.4874in"
        viewBox="0 0 2492.95 755.093" xml:space="preserve" color-interpolation-filters="sRGB" >

<g id="shape1014-243" v:mID="1014" v:groupContext="shape" transform="translate(30.3431,-54.0037)">
            <title>Team frame.1171</title>
            <desc>Test</desc>
            <v:custProps>
                <v:cp v:nameU="Theme" v:lbl="MY_UNIQUE_ID_1" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false"
                        v:ask="false" v:langID="0" v:cal="0" v:val="VT0(0):26"/>
            </v:custProps>
            <v:textBlock v:margins="rect(0,0,0,0)" v:tabSpace="42.5197"/>
            <v:textRect cx="100.34" cy="791.095" width="200.69" height="72.0035"/>
            <path d="M56.21 84.35 L55.85 84.35 L17.01 84.35 A17.0079 17.0079 -180 0 0 0 101.35 L0 738.09 A17.0079 17.0079 -180 0
                         0 17.01 755.09 L183.67 755.09 A17.0079 17.0079 -180 0 0 200.68 738.09 L200.68 101.35 A17.0079 17.0079 -180
                         0 0 183.67 84.35 L144.83 84.35" />
            <text x="5.13" y="809.09"  v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Arrivals</text>       
</g>
</svg>

  • Related