Обработка управляющих символов XML (например, кавычек) с использованием JAXB Marshaller - PullRequest
8 голосов
/ 14 декабря 2010

Мне нужно сериализовать Java-объект XML в XML-файл, используя Marshaller JAXB (версия 2.2 JAXB). Теперь в объекте xml у меня есть тег, который содержит строковое значение , такое что:

"<"tagA>
**"<"YYYYY>done"<"/YYYYY>**
"<"/tagA>

Теперь, как вы видите, это строковое значение снова содержит теги. Я хочу, чтобы это было так же записано в файле xml.

Но JAXB Marshaller преобразует эти значения, такие как:

"&"lt;YYYYY"&"gt;"&"#xD;done ... и т. Д.

Я не могу обрабатывать эти escape-символы отдельно, используя JAXB 2.2 Возможно ли это в любом случае?

Любая помощь в этом отношении будет велика ..

Заранее спасибо, Абхинав Мишра

Ответы [ 5 ]

8 голосов
/ 16 декабря 2010

Сделайте это, установив следующее свойство для JAXB Marshaller:

marshaller.setProperty("jaxb.encoding", "Unicode");
7 голосов
/ 25 апреля 2012

Есть один более простой способ. Сначала используйте пользовательскую escape-последовательность:

m.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {
    @Override
    public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
        out.write( ch, start, length ); 
    }
}); 

Затем поместите его в строку, как указано ниже

StringWriter writer = new StringWriter();
m.marshal(marshalObject, writer);

, а затем создайте объект документа из автора, упомянутого ниже

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource( new StringReader( writer.toString() ) );
Document doc = builder.parse( is );

проблема с escape-символами будет решена

2 голосов
/ 30 января 2018

С маршаллером JAXB, если вы хотите получить полный контроль над тем, какие символы экранировать (например, "\ '"), вам нужно добавить свойство:

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler());

и создайте новый класс CustomCharacterEscapeHandler

import com.sun.xml.bind.marshaller.CharacterEscapeHandler;

import java.io.IOException;
import java.io.Writer;

public class CustomCharacterEscapeHandler implements CharacterEscapeHandler {

    public CustomCharacterEscapeHandler() {
        super();
    }

    public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
        // avoid calling the Writerwrite method too much by assuming
        // that the escaping occurs rarely.
        // profiling revealed that this is faster than the naive code.
        int limit = start+length;
        for (int i = start; i < limit; i++) {
            char c = ch[i];
            if(c == '&' || c == '<' || c == '>' || c == '\'' || (c == '\"' && isAttVal) ) {
                if(i!=start)
                    out.write(ch,start,i-start);
                start = i+1;
                switch (ch[i]) {
                    case '&':
                        out.write("&amp;");
                        break;
                    case '<':
                        out.write("&lt;");
                        break;
                    case '>':
                        out.write("&gt;");
                        break;
                    case '\"':
                        out.write("&quot;");
                        break;
                    case '\'':
                        out.write("&apos;");
                        break;
                }
            }
        }

        if( start!=limit )
            out.write(ch,start,limit-start);
    }
}

Надеюсь, это поможет.

2 голосов
/ 14 декабря 2010

Вы можете использовать структуру CDATA.Стандарт JAXB не распространяется на эту структуру.Для этого есть расширение EclipseLink JAXB (MOXy) (я технический руководитель).Проверьте мой ответ на связанный вопрос:

В нем описывается аннотация @XmlCDATA в MOXy:

import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;

@XmlRootElement(name="c")
public class Customer {

   private String bio;

   @XmlCDATA
   public void setBio(String bio) {
      this.bio = bio;
   }

   public String getBio() {
      return bio;
   }

}

Для получения дополнительной информации см .:

1 голос
/ 04 августа 2011

В зависимости от того, что именно вы ищете, вы можете:

  • отключить экранирование символов
  • или используйте строку CDATA, поддержку которой можно добавить в JAXB с небольшой настройкой
...