2016-11-03 8 views
0

Мне предоставлен XML-файл с инструкцией для чтения, редактирования и записи с использованием Jackson and Woodstox (согласно рекомендации в документации). По большей части это было не слишком сложно; Они оба довольно хороши в том, что он делает. На данный момент я столкнулся с проблемой:Толкование символов в кодировке XML в JavaScript Jackson/Woodstox

Мои объекты XML сами содержат объекты XML. Например:

<XMLObject> 
    <OuterObject attributeOne="1" attributeTwo="2" attributeThree="&gt;"> 
     <InnerObject>&lt;NestedObject&gt;Blah&lt;/NestedObject&gt;</InnerObject> 
    </OuterObject> 
    <OuterObject attributeOne="11" attributeTwo="22" attributeThree="&lt;"> 
     <InnerObject>&lt;NestedObject&gt;Blah&lt;/NestedObject&gt;</InnerObject> 
    </OuterObject> 
    <OuterObject attributeOne="111" attributeTwo="222" attributeThree="3" /> 
<XMLObject> 

В тот момент я прочитал файл XML в мой Джексон-аннотированный объекта Java, все эти экземпляры &lt; и &gt; преобразуются Woodstox в < и > соответственно. Когда я пишу объект обратно в файл XML, < становится &lt; но > остается >

<XMLObject> 
    <OuterObject attributeOne="1" attributeTwo="2" attributeThree=">"> 
     <InnerObject>&lt;NestedObject>Blah&lt;/NestedObject></InnerObject> 
    </OuterObject> 
    <OuterObject attributeOne="11" attributeTwo="22" attributeThree="&lt;"> 
     <InnerObject>&lt;NestedObject>Blah&lt;/NestedObject></InnerObject> 
    </OuterObject> 
    <OuterObject attributeOne="111" attributeTwo="222" attributeThree="3" /> 
<XMLObject> 

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

@RequestMapping("readXML") 
public @ResponseBody CustomXMLObject readXML() throws Exception { 
    File inputFile = new File(FILE_PATH); 
    XmlMapper mapper = new XmlMapper(); 
    CustomXMLObject value = mapper.readValue(inputFile, CustomXMLObject .class); 

    return value; 
} 

И мой объект Jacob-annotated Java будет выглядеть примерно так, как показано в примере, приведенном выше:

import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; 

@JsonInclude(JsonInclude.Include.NON_NULL) 
public class CustomXMLObject { 
    @JacksonXmlProperty(isAttribute=true) 
    private long attributeOne; 
    @JacksonXmlProperty(isAttribute=true) 
    private String attributeTwo; 
    @JacksonXmlProperty(isAttribute=true) 
    private String attributeThree; 
    @JacksonXmlProperty(localName = "InnerObject") 
    private String innerObject; 


    public long getAttributeOne() { 
     return attributeOne; 
    } 

    public void setAttributeOne(long attributeOne) { 
     this.attributeOne = attributeOne; 
    } 

    public String getAttributeTwo() { 
     return attributeTwo; 
    } 

    public void setAttributeTwo(String attributeTwo) { 
     this.attributeTwo = attributeTwo; 
    } 

    public String getAttributeThree() { 
     return attributeThree; 
    } 

    public void setAttributeThree(String attributeThree) { 
     this.attributeThree = attributeThree; 
    } 

    public String getInnerObject() { 
     return innerObject; 
    } 

    public void setInnerObject(String innerObject) { 
     this.innerObject = innerObject; 
    } 
} 

Наконец, мои зависимости выглядеть следующим образом:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency> 
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-test</artifactId> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>com.jayway.jsonpath</groupId> 
    <artifactId>json-path</artifactId> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>com.fasterxml.jackson.module</groupId> 
    <artifactId>jackson-module-jaxb-annotations</artifactId> 
    <version>2.5.0</version> 
</dependency> 
<dependency> 
     <groupId>com.fasterxml.jackson.dataformat</groupId> 
     <artifactId>jackson-dataformat-xml</artifactId> 
     <version>2.8.4</version> 
</dependency> 
<dependency> 
    <groupId>org.codehaus.woodstox</groupId> 
    <artifactId>woodstox-core-asl</artifactId> 
    <version>4.4.1</version> 
</dependency> 

Это, как представляется, происходит из-за использования Джексона BufferingXmlWriter Woodstox». Этот конкретный автор будет перехватывать эти символы и кодировать их, и не кажется, каким-либо образом обойти это решение:

private final void writeAttrValue(String value, int len) throws IOException { 
    int inPtr = 0; 
    char qchar = this.mEncQuoteChar; 
    int highChar = this.mEncHighChar; 

    while(true) { 
     String ent = null; 

     while(true) { 
      if(inPtr >= len) { 
       return; 
      } 

      char c = value.charAt(inPtr++); 
      if(c <= 60) { 
       if(c < 32) { 
        if(c == 13) { 
         if(this.mEscapeCR) { 
          break; 
         } 
        } else { 
         if(c == 10 || c == 9 || this.mXml11 && c != 0) { 
          break; 
         } 

         c = this.handleInvalidChar(c); 
        } 
       } else { 
        if(c == qchar) { 
         ent = this.mEncQuoteEntity; 
         break; 
        } 

        if(c == 60) { 
         ent = "&lt;"; 
         break; 
        } 

        if(c == 38) { 
         ent = "&amp;"; 
         break; 
        } 
       } 
      } else if(c >= highChar) { 
       break; 
      } 

      if(this.mOutputPtr >= this.mOutputBufLen) { 
       this.flushBuffer(); 
      } 

      this.mOutputBuffer[this.mOutputPtr++] = c; 
     } 

     if(ent != null) { 
      this.writeRaw(ent); 
     } else { 
      this.writeAsEntity(value.charAt(inPtr - 1)); 
     } 
    } 
} 

Так подытожить проблему в конце концов, я был дан файл XML. Этот XML-файл содержит атрибуты и элементы, которые сами содержат символы (< и >), которые были закодированы (&lt; и &gt;), чтобы не сломать XML. Когда Woodstox читает файл, вместо того чтобы передать мой объект Java фактическую строку, содержащуюся в XML, он декодирует символ. При записи только < перекодируется как &lt;. Кажется, это происходит потому, что Джексон использует BufferingXmlWriter от Woodstox, который, похоже, не настраивается, чтобы избежать кодирования этих символов.

В результате, мой вопрос заключается в следующем:

Могу ли я настроить объект Джексона использовать для чтения Woodstox XML, который позволит моим читать и писать символы в моем файле XML без дальнейшего кодирования, или сделать Мне нужно искать другое решение для моих нужд?

ответ

0

Вы можете настроить базовые XMLOutputFactory2, чтобы использовать CharacterEscapes, что может указывать переопределение того, что по умолчанию экранируется. Будет ли это:

http://www.cowtowncoder.com/blog/archives/2012/08/entry_476.html

работа?

EDIT: извинения за предложение выше - это не работает с XML, а просто с JSON. Я должен был дважды проверить его. Хотя есть рабочий элемент, чтобы он также работал с XML, этого пока не существует (по состоянию на ноябрь 2016 г.).

+0

К сожалению, нет. Согласно https://github.com/FasterXML/jackson-dataformat-xml/issues/75 текущая сборка не поддерживает функцию Escape Escape. Я попытался реализовать это независимо от того, что нет. –

+0

@MatthewSnook да и нет: текущая версия не поддерживает удобный доступ; но ничего не мешает вам предоставить специально сконфигурированный 'XMLOutputFactory2' для' XmlMapper' (или, может быть, через 'XmlFactory', я забыл детали). Так что есть немного больше проводки для использования, но это должно быть выполнимо. – StaxMan

+0

Хм .... ну, тогда мне нужно немного больше рекомендаций. Просто после того, как процесс из этого сообщения в блоге, похоже, ничего не делает для чтения/записи данных. –