Chrome 22 выводит недопустимый XML, если атрибуты имеют пространство имен xlink
у меня есть следующий минимальный фрагмент JavaScript:
var xml = '<El a:title="T" a:href="H" xmlns:a="http://www.w3.org/1999/xlink" />';
var dom = new DOMParser().parseFromString(xml, 'text/xml');
xml = new XMLSerializer().serializeToString(dom);
когда я выполняю код в большинстве браузеров (просто вставьте его в консоль JavaScript Вашего браузера), проанализированный затем сериализованный XML эквивалентен оригиналу. Например, на Chrome 8 я получаю:
<El xmlns:a="http://www.w3.org/1999/xlink" a:title="T" a:href="H"/>
однако в Chrome 22 тот же фрагмент кода изменяет XML на:
<El xmlns:a="http://www.w3.org/1999/xlink" xlink:title="T" xlink:href="H"/>
обратите внимание, что префикс пространства имен xlink
используемые атрибуты title и href не определено в любом месте, поэтому XML теперь недействителен. Как вы, вероятно, можете себе представить, это вызывает всевозможные проблемы для кода, который пытается впоследствии использовать XML.
это ошибка в XMLSerializer или мне не хватает некоторых тонкостей о том, как DOM должен быть сериализован?
также кто-нибудь нашел обходной путь, который я могу поместить в код, в отличие от того, чтобы XML соответствовал очевидному предпочтению использовать xlink
в качестве префикса для XLink пространство имен?
обновление
я провел дополнительное тестирование, и проблема, похоже, вызвана тем, что XMLSerializer распознает пространство имен XLink и настаивает на выводе xlink
префикс для него, без надлежащей регистрации этого префикса.
так что этот фрагмент работает нормально:
var xml = '<El a:title="T" a:href="H" xmlns:a="any-other-namespace-uri" />';
var dom = new DOMParser().parseFromString(xml, 'text/xml');
xml = new XMLSerializer().serializeToString(dom);
Итак, здесь я изменил URL пространства имен на что-то менее известное, и вывод теперь действителен:
<El xmlns:a="any-other-namespace-uri" a:title="T" a:href="H"/>
следующий фрагмент также отлично работает:
var xml = '<El a:title="T" a:href="H" xmlns:a="http://www.w3.org/2000/xlink" />';
var dom = new DOMParser().parseFromString(xml, 'text/xml');
xml = new XMLSerializer().serializeToString(dom);
поэтому в этом случае мы используем префикс "expected" для пространства имен XLink, а затем сериализуем без проблем:
<El xmlns:a="http://www.w3.org/2000/xlink" a:title="T" a:href="H"/>
1 ответов
Я все еще уверен, что в Chrome есть ошибка XMLSerializer
, скорее всего, введено при обращении к SVG обработка атрибутов XLink, которые Barbarrosa указал на. Но учитывая отсутствие реакции на сообщить об ошибке Я сделал для этого, мы должны были двигаться вперед и работать над проблемой.
мы работаем вокруг проблемы, вызывая эту функцию на documentElement
:
function EnsureXLinkNamespaceOnElement(element)
{
if (element.nodeType == 1)
{
var usesXLinkNamespaceUri = false;
var hasXLinkNamespacePrefixDefined = false;
for (var i = 0; i < element.attributes.length; i++)
{
var attribute = element.attributes[i];
if (attribute.specified)
{
if (attribute.name.indexOf("xmlns:xlink") == 0)
{
hasXLinkNamespacePrefixDefined = true;
}
else if (attribute.namespaceURI == "http://www.w3.org/1999/xlink")
{
usesXLinkNamespaceUri = true;
}
}
}
if (usesXLinkNamespaceUri && !hasXLinkNamespacePrefixDefined)
{
element.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
}
for (i = 0; i < element.childNodes.length; i++)
{
EnsureXLinkNamespaceOnElement(element.childNodes[i]);
}
}
}
функция просто проверяет, что xmlns:xlink
атрибут объявляется для любого элемента, который имеет атрибут в пространстве имен XLink. Поскольку функция пересекает дерево и, следовательно, может быть довольно трудоемкой, я вызываю ее только для версий Chrome 22 и выше.
обратите внимание, что в большинстве случаев вы также можете сойти с рук, просто добавив xmlns:xlink
пространство имен в элементе документа, так как оно будет унаследовано оттуда. Но в нашем случае был какой-то другой код, который удаляет элемент документа с помощью регулярного выражения, поэтому мы решили чтобы играть в нее безопасно и просто добавить атрибут везде, где это может понадобиться.
обновление (20130324):
на ошибка был исправлен и проверен в Chrome Canary 26. Я смог проверить это сам на версии 25.0.1364.172 m
тоже.