Доступ к атрибутам узла SVG

У меня есть файл SVG, который я показываю и из которого я хочу получить информацию, когда я нажимаю на определенный элемент.

Вот часть SVG:

        <g id="group327-2702" transform="translate(1539.96,-1043.15)" v:mID="327" v:groupContext="group">
        <v:custProps>
            <v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/>
            <v:cp v:nameU="labelFR" v:lbl="labelFR" v:type="0" v:sortKey="3" v:langID="1036" v:val="VT4(Carnet d&#39;ordres)"/>
            <v:cp v:nameU="labelEN" v:lbl="labelEN" v:type="0" v:sortKey="4" v:langID="1036"
                    v:val="VT4(Order Management System )"/>
            <v:cp v:nameU="type" v:lbl="Type" v:type="0" v:langID="1036" v:val="VT4(Business)"/>
            <v:cp v:nameU="appLevel" v:lbl="appLevel" v:type="0" v:langID="1036" v:val="VT4(3)"/>
            <v:cp v:nameU="name" v:lbl="name" v:type="0" v:sortKey="2" v:langID="1036" v:val="VT4(MCE Trading)"/>
            <v:cp v:nameU="External" v:lbl="External" v:type="0" v:langID="1036" v:val="VT4(FALSE)"/>
            <v:cp v:nameU="_VisDM_type" v:lbl="type" v:langID="1036" v:val="VT4(Business)"/>
            <v:cp v:nameU="_VisDM_status" v:lbl="status" v:type="2" v:langID="1036" v:val="VT0(1):26"/>
        </v:custProps>
        <v:userDefs>
            <v:ud v:nameU="msvStructureType" v:prompt="" v:val="VT4(Container)"/>
            <v:ud v:nameU="msvSDContainerMargin" v:prompt="" v:val="VT0(0.078740157480315):24"/>
            <v:ud v:nameU="Label" v:prompt="" v:val="VT0(2):26"/>
            <v:ud v:nameU="ShapeVersion" v:prompt="" v:val="VT0(1):26"/>
            <v:ud v:nameU="LightColorText" v:prompt="" v:val="VT0(0):5"/>
        </v:userDefs>
        <title>Module.52.327</title>
        <g id="shape328-2703" v:mID="328" v:groupContext="shape">
            <title>Feuille.328</title>
            <v:userDefs>
                <v:ud v:nameU="visVersion" v:val="VT0(14):26"/>
            </v:userDefs>
            <rect x="0" y="1652.6" width="93.5433" height="31.1811" rx="2.83465" ry="2.83465" class="st72"/>
        </g>
        <g id="shape327-2705" v:mID="327" v:groupContext="groupContent">
            <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
            <v:textRect cx="46.7717" cy="1668.19" width="93.55" height="31.1811"/>
            <text x="28.54" y="1661.89" class="st73" v:langID="1036"><v:paragraph v:horizAlign="1"/><v:tabList/>MCE Trading<v:newlineChar/><v:newlineChar/><tspan
                        x="7.63" dy="2.4em" class="st5">Order Management System </tspan> </text>            </g>
    </g>

Мне нужно получить доступ к атрибутам первого дочернего элемента моего узла <v:custProps>:

<v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/>

Странно то, что между каждым узлом есть пустой текстовый брат: например, если я сделаю это:

var msg = "";
    msg += "target nodeName, width x height : " + evt.target.nodeName + ", " + evt.target.getAttributeNodeNS(null, 'width').nodeValue + " x " + evt.target.getAttributeNodeNS(null, 'height').nodeValue + "\n\n";

    msg += "parent nodeName, id : " + evt.target.parentNode.nodeName + ", " + evt.target.parentNode.id + "\n\n";

    msg += "parent previousSibling nodeName : " + evt.target.parentNode.previousSibling.nodeName + "\n\n";

    msg += "parent 2 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 3 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 4 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 5 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 6 previousSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.nodeName + "\n\n";

    msg += "parent 6 previousSibling firstChild nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.firstChild.nodeName + "\n\n";

    msg += "parent 6 previousSibling firstChild nextSibling nodeName : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.firstChild.nextSibling.nodeName + "\n\n";

alert(msg);

Результат:

target nodeName, ширина x высота: прямоугольник, 93,5433 x 31,1811

родительский nodeName, идентификатор: g, shape328-2703

родитель предыдущийSibling nodeName : #text

родитель 2 предыдущаяSibling nodeName : title

родитель 3 предыдущий одноуровневый nodeName : #text

родитель 4 предыдущаяSibling nodeName : v:userDefs

родитель 5 предыдущий одноуровневый nodeName : #text

родитель 6 предыдущий одноуровневый nodeName : v: custProps

родитель 6 предыдущийСиблинг firstChild nodeName : #text

родитель 6 previousSibling firstChild nextSibling nodeName : v:cp

Итак, теперь я получил доступ (странным образом) к моему узлу <v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/>, я пытаюсь получить атрибуты.

Например: msg += "parent 6 previousSibling firstChild nextSibling v:nameU : " + evt.target.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling.firstChild.nextSibling.getAttributeNS(null, 'v:nameU') + "\n\n";

Но это не работает. Я попытался добавить идентификатор в строку, и я могу получить атрибут идентификатора. Но для существующих атрибутов это не работает.

Итак, почему между каждым узлом есть родственный текст, которого нет в структуре svg?

Почему я не могу получить доступ к атрибутам, которые пытаюсь получить? Это потому, что они взяты из Visio (v:)


person Ellone    schedule 20.04.2015    source источник


Ответы (2)


Я думаю, что вы ищете nextElementSibling и previousElementSibling.

TextNodes — это узлы, а пробелы между тегами в вашем документе могут быть TextNodes.

var g=document.querySelector('#group327-2702');
var cpElement = g.firstElementChild.firstElementChild.nextElementSibling;
var r = cpElement.getAttributeNS(null, "v:nameu")+' '+
    cpElement.getAttributeNS(null, "v:lbl")+' '+
    cpElement.getAttributeNS(null, "v:type")+' '+
    cpElement.getAttributeNS(null, "v:sortkey")+' '+
    cpElement.getAttributeNS(null, "v:langid")+' '+
    cpElement.getAttributeNS(null, "v:val");

document.querySelector('p').textContent= r;
<svg><g id="group327-2702" transform="translate(1539.96,-1043.15)" v:mID="327" v:groupContext="group"><v:custProps>
            <v:cp v:nameU="idApplication" v:lbl="idApplication" v:type="0" v:sortKey="1" v:langID="1036" v:val="VT4(143)"/>
            <v:cp v:nameU="labelFR" v:lbl="labelFR" v:type="0" v:sortKey="3" v:langID="1036" v:val="VT4(Carnet d&#39;ordres)"/>
            <v:cp v:nameU="labelEN" v:lbl="labelEN" v:type="0" v:sortKey="4" v:langID="1036"
                    v:val="VT4(Order Management System )"/>
            <v:cp v:nameU="type" v:lbl="Type" v:type="0" v:langID="1036" v:val="VT4(Business)"/>
            <v:cp v:nameU="appLevel" v:lbl="appLevel" v:type="0" v:langID="1036" v:val="VT4(3)"/>
            <v:cp v:nameU="name" v:lbl="name" v:type="0" v:sortKey="2" v:langID="1036" v:val="VT4(MCE Trading)"/>
            <v:cp v:nameU="External" v:lbl="External" v:type="0" v:langID="1036" v:val="VT4(FALSE)"/>
            <v:cp v:nameU="_VisDM_type" v:lbl="type" v:langID="1036" v:val="VT4(Business)"/>
            <v:cp v:nameU="_VisDM_status" v:lbl="status" v:type="2" v:langID="1036" v:val="VT0(1):26"/>
        </v:custProps>
        <v:userDefs>
            <v:ud v:nameU="msvStructureType" v:prompt="" v:val="VT4(Container)"/>
            <v:ud v:nameU="msvSDContainerMargin" v:prompt="" v:val="VT0(0.078740157480315):24"/>
            <v:ud v:nameU="Label" v:prompt="" v:val="VT0(2):26"/>
            <v:ud v:nameU="ShapeVersion" v:prompt="" v:val="VT0(1):26"/>
            <v:ud v:nameU="LightColorText" v:prompt="" v:val="VT0(0):5"/>
        </v:userDefs>
        <title>Module.52.327</title>
        <g id="shape328-2703" v:mID="328" v:groupContext="shape">
            <title>Feuille.328</title>
            <v:userDefs>
                <v:ud v:nameU="visVersion" v:val="VT0(14):26"/>
            </v:userDefs>
            <rect x="0" y="1652.6" width="93.5433" height="31.1811" rx="2.83465" ry="2.83465" class="st72"/>
        </g>
        <g id="shape327-2705" v:mID="327" v:groupContext="groupContent">
            <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
            <v:textRect cx="46.7717" cy="1668.19" width="93.55" height="31.1811"/>
            <text x="28.54" y="1661.89" class="st73" v:langID="1036"><v:paragraph v:horizAlign="1"/><v:tabList/>MCE Trading<v:newlineChar/><v:newlineChar/><tspan
                        x="7.63" dy="2.4em" class="st5">Order Management System </tspan> </text>            </g>
    </g></svg>

<p id="log"></p>

Кроме того, благодаря вашей проблеме я обнаружил, что вы должны использовать строчные буквы для атрибутов, которые вы ищете, с помощью getAttributeNS()

person Kaiido    schedule 20.04.2015
comment
Эй, спасибо! Это то, что я предположил о текстовом узле. Однако, в нижнем регистре или нет, getAttributeNS() не работает. Но getAttribute есть (с тем же корпусом). Так что мне удалось заставить его работать сейчас. Я опубликую ответ. Однако я не понимаю, почему для моего элемента <title> hasChildNodes() возвращает true, поскольку мой <title> пуст, а firstElementChild равен null . Я предполагаю, что это пустой текстовый узел. Мне понадобится метод hasChildElements, чтобы сделать это без этого конкретного случая, который я обрабатываю вручную. - person Ellone; 21.04.2015
comment
@Ellone, вместо hasChildNodes() вы можете проверить длину element.chidren, если она равна › 0, то у вашего элемента есть дочерние элементы. А насчет getAttribute, я искренне не понимаю, атрибуты HTML нечувствительны к регистру, а XML... Так что в моем понимании должно быть наоборот... - person Kaiido; 21.04.2015
comment
Спасибо, я попробую это. Прямо сейчас я пытаюсь изменить значок курсора, когда он находится над элементом, соответствующим idApplication, поэтому в условии, которое я пытался добавить: if (efc.getAttribute("v:nameU") == "idApplication") { efc.style.cursor = "help"; ... Но я предполагаю, что делаю это неправильно. - person Ellone; 21.04.2015
comment
Да, вы должны применить стиль к наведенному element, а не к вашему efc - person Kaiido; 21.04.2015
comment
Это тоже не работает. Но на самом деле я думаю, что это потому, что мой SVG находится в другом файле. Я включаю его в свой html, используя <object>, поэтому не знаю, как этого добиться. - person Ellone; 21.04.2015

Итак, мне удалось получить атрибут, который я хотел, следующим образом, спасибо Кайидо за вашу помощь:

var element = evt.target.parentNode;
    while (element) {
        if (element.children.length > 0) {
            var efc = element.firstElementChild;
            if (efc.hasAttribute("v:nameU")) {
                if (efc.getAttribute("v:nameU") == "idApplication") {
                    element.style.cursor = "help";
                    var regExp = /\(([^)]+)\)/;
                    var appId = efc.getAttribute("v:val").match(regExp);
                    alert("id : " + appId[1]);
                    break;
                }
                else
                    element = element.previousElementSibling;
            }
            else
                element = element.previousElementSibling;
        }
        else
            element = element.previousElementSibling;
    }
}

Но эта строка element.style.cursor = "help"; не работает, значок курсора остается прежним над элементом, соответствующим idApplication.

Нужно знать, что мой svg находится в другом файле, включенном в мой html через тег <object>.

person Ellone    schedule 21.04.2015