JAXB: Как избежать повторного определения пространства имен для xmlns:xsi

У меня есть установка JAXB, где я использую @XmlJavaTypeAdapter для замены объектов типа Person с объектами типа PersonRef то единственное содержит UUID человека. Это работает превосходное. Однако сгенерированная XML повторно объявляет то же пространство имен (xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance") каждый раз это используется. В то время как это обычно хорошо, это просто не чувствует себя хорошо.

Как я могу настроить JAXB для объявления xmlns:xsi в самом начале документа? Я могу вручную добавить объявления пространства имен к корневому элементу?

Вот пример того, что я хочу к achive:

Текущий:

<person uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a">
    <relation type="CHILD"> 
        <to xsi:type="personRef" uuid="56a930c0-5499-467f-8263-c2a9f9ecc5a0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> 
    </relation> 
    <relation type="CHILD"> 
        <to xsi:type="personRef" uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> 
    </relation>
    <!-- SNIP: some more relations -->
</person>

Требуемый:

<person uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <relation type="CHILD"> 
        <to xsi:type="personRef" uuid="56a930c0-5499-467f-8263-c2a9f9ecc5a0"/> 
    </relation> 
    <relation type="CHILD"> 
        <to xsi:type="personRef" uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a"/> 
    </relation>
    <!-- SNIP: some more relations -->
</person>
20
задан sfussenegger 12 February 2010 в 13:39
поделиться

4 ответа

Вы можете сделать это с помощью кода:

marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() {
                @Override
                public String[] getPreDeclaredNamespaceUris() {
                    return new String[] { 
                        XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
                    };
                }

                @Override
                public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
                    if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI))
                        return "xsi";
                    if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI))
                        return "xs";
                    if (namespaceUri.equals(WellKnownNamespace.XML_MIME_URI))
                        return "xmime";
                    return suggestion;

                }
            });
6
ответ дан 29 November 2019 в 23:57
поделиться

Похоже на проблему настройки пространства имен настройки JAXB

Когда вы маршалируете XML-документ с помощью JAXB 1.0, объекта Marshaller, объекта JAXB, который управляет процессом маршалинг, предоставляет объявления пространств имен в результирующем XML-документе. Иногда Marshaller создает множество объявлений пространств имен, которые выглядят избыточными, например:

   <?xml version="1.0"?>
   <root>
      <ns1:element xmlns:ns1="urn:foo"> ... </ns1:element>
      <ns2:element xmlns:ns2="urn:foo"> ... </ns2:element>
      <ns3:element xmlns:ns3="urn:foo"> ... </ns3:element>
   </root>

JAXB 2.0 изменяет это поведение. Если вы используете JAXB 2.0 (или более позднюю версию) для маршалинга XML-документа, Marshaller объявляет все статически известные универсальные идентификаторы ресурсов (URI) пространства имен, то есть те URI, которые используются в качестве имен элементов или атрибутов в аннотациях JAXB.

JAXB может также объявлять дополнительные пространства имен в середине документа XML, например, когда полное имя ( QName ), которое используется в качестве значения атрибута или элемента, требует нового URI пространства имен, или когда Узлу объектной модели документа (DOM) в дереве содержимого требуется новый URI пространства имен. Такое поведение может привести к созданию XML-документа, в котором будет много объявлений пространств имен с автоматически сгенерированными префиксами пространств имен.

Проблема в том, что автоматически сгенерированные префиксы пространства имен, такие как ns1, ns2 и ns3, не удобны для пользователя - они обычно не помогают людям понять упорядоченный XML.

К счастью, JAXB 2.0 (или более поздняя версия) предоставляет интерфейс поставщика услуг (SPI) с именем com.sun.xml.bind.marshaller.NamespacePrefixMapper , который можно использовать для указания более полезных префиксов пространства имен для сортировки.

Когда программа JAXBSample упорядочивает XML-документ в первый раз, она делает это без использования класса NamespacePrefixMapper . В результате Marshaller автоматически генерирует префикс пространства имен, в данном случае ns2.

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <ns2:JustAnElement xmlns:ns2="a">
       <foo>true</foo>
   </ns2:JustAnElement>

Пример конфигурации, исключающей повторение пространства имен:

Второй маршаллинг, выполняемый программой JAXBSample , использует класс NamespacePrefixMapper следующим образом:

   NamespacePrefixMapper m = new PreferredMapper();
               marshal(jc, e, m);

   public static class PreferredMapper extends NamespacePrefixMapper {
           @Override
           public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
               return "mappedNamespace" + namespaceUri;
           }
       }

getPreferredPrefix () в классе PreferredMapper возвращает предпочтительный префикс, в данном случае, mappedNamespacea , который должен быть объявлен в корневом элементе упорядоченного XML.

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <mappedNamespacea:JustAnElement xmlns:mappedNamespacea="a">
       <foo>true</foo>
   </mappedNamespacea:JustAnElement>
9
ответ дан 29 November 2019 в 23:57
поделиться

Это XML, поэтому вы можете обработать вывод с помощью DOM или XSLT, чтобы избавиться от многочисленных ссылок на пространство имен.

0
ответ дан 29 November 2019 в 23:57
поделиться

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

marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
17
ответ дан 29 November 2019 в 23:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: