В модели данных XML узлы пространства имен фактически не читаются из родительского элемента, но каждый элемент имеет свои собственные узлы пространства имен.Поэтому простое добавление нового пространства имен по умолчанию к корневому элементу не работает, но приводит к документу, подобному этому
<root xmlns="namespaceURL">
<child xmlns=""/>
...
</root>
Обратите внимание на появление пустого пространства имен по умолчанию xmlns=""
на дочерних элементах.Что на самом деле нужно сделать, так это изменить пространство имен каждого узла или создать новый документ с требуемым пространством имен по умолчанию и скопировать содержимое, имена элементов и атрибутов и т. Д. Старого документа в новый.Это можно сделать, рекурсивно просматривая исходный документ.Я слышал, что реализация Java DOM может быть трудоемкой.Одним из коротких путей может быть чтение документа с помощью DOM, не поддерживающего пространство имен, а затем добавление в качестве атрибута нового пространства имен по умолчанию.Другое решение состоит в том, чтобы изменить пространство имен с помощью преобразования XSLT, что кажется вполне подходящим в этом случае, поскольку вы фактически уже генерируете выходные данные с помощью преобразования XSLT.
Используйте эту таблицу стилей XSLT, чтобы добавить новое пространство имен по умолчанию ирасположение схемы к корневому элементу.Эта таблица стилей сохраняет старые пространства имен, но добавляет все элементы в новое пространство имен по умолчанию, если они ранее находились в пространстве без имен.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- Template to add a default namespace to a document -->
<!-- Elements without a namespace are "moved" to default namespace -->
<!-- Elements with a namespace are copied as such -->
<!-- string for default namespace uri and schema location -->
<xsl:variable name="ns" select="'namespaceURL'"/>
<xsl:variable name="schemaLoc" select="'namespaceURL pathToMySchema.xsd'"/>
<!-- template for root element -->
<!-- adds default namespace and schema location -->
<xsl:template match="/*" priority="1">
<xsl:element name="{local-name()}" namespace="{$ns}">
<xsl:attribute name="xsi:schemaLocation"
namespace="http://www.w3.org/2001/XMLSchema-instance">
<xsl:value-of select="$schemaLoc"/>
</xsl:attribute>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!--template for elements without a namespace -->
<xsl:template match="*[namespace-uri() = '']">
<xsl:element name="{local-name()}" namespace="{$ns}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!--template for elements with a namespace -->
<xsl:template match="*[not(namespace-uri() = '')]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!--template to copy attributes, text, PIs and comments -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Вместо создания преобразователя с
Transformer trans = transfac.newTransformer();
(который создает итаблица стилей, которая выполняет преобразование тождества), создайте источник ввода XSLT и передайте его в качестве параметра newTransformer()
javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
Transformer trans = transFact.newTransformer(xsltSource);
, где xsltFile
- это объект File
, указывающий на этот файл XSLT.
Установите выходные свойства по своему усмотрению и вызовите transform()
, как в вашем примере кода.Результат должен быть тем, что вы хотели, но я не проверял это в Java .Данный XSLT-файл протестирован для некоторых тривиальных случаев, и в конце этого ответа приведен пример ввода и вывода.
Некоторые незначительные замечания:
- Исходный объект документа не являетсяизменены в этом процессе.Новое пространство имен по умолчанию появляется только в выходных данных метода
transform()
. - Префикс пространства имен для пространства имен экземпляра схемы обычно равен
xsi:
, а не xs:
, как в примере кода (xs:
isиспользуется в определениях схемы (а также xsd:
)).
Пример ввода и вывода для таблицы стилей XSLT, показанной выше
Ввод:
<root>
<child>text</child>
<child attribute="attr-value"/>
<?pi-target pi-content?>
<nsx:ns-child xmlns:nsx="ns1x">
<no-ns-child>text</no-ns-child>
<!-- comment -->
<nsx:ns-child nsx:ns-attribute="nsx-attr-value">text</nsx:ns-child>
</nsx:ns-child>
<defns-child xmlns="default-ns">
<def-child attr="val">text</def-child>
<child xmlns=""/>
</defns-child>
<child>text</child>
</root>
Вывод:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="namespaceURL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="namespaceURL pathToMySchema.xsd">
<child>text</child>
<child attribute="attr-value"/>
<?pi-target pi-content?>
<nsx:ns-child xmlns:nsx="ns1x">
<no-ns-child>text</no-ns-child>
<!-- comment -->
<nsx:ns-child nsx:ns-attribute="nsx-attr-value">text</nsx:ns-child>
</nsx:ns-child>
<defns-child xmlns="default-ns">
<def-child attr="val">text</def-child>
<child xmlns="namespaceURL"/>
</defns-child>
<child>text</child>
</root>