2015-04-14 2 views
3

J'utilise XStream pour oxm (Java Objects to xml). NameCoder utilise le trait de soulignement comme caractère d'échappement par défaut (plus d'informations ci-dessous) et puisque j'ai ext_data comme balise xml, il est écrit comme ext__data. XStream mappe les noms de classe Java et les noms de champ en balises ou attributs XML. Malheureusement, cette correspondance ne peut pas être 1: 1, car certains caractères utilisés pour les identifiants en Java ne sont pas valides dans les noms XML. Par conséquent XStream utilise un XmlFriendlyNameCoder pour remplacer ces caractères par un remplacement. Par défaut, ce NameCoder utilise un trait de soulignement comme caractère d'échappement et doit donc également s'échapper du trait de soulignement. Vous pouvez fournir une instance configurée différente du XmlFriendlyNameCoder ou une implémentation complète différente comme theNoNameCoder pour empêcher le codage du nom. Cependant, il est de votre responsabilité de vous assurer que les noms résultants sont valides pour XML. (http://x-stream.github.io/faq.html)XStream double trait de soulignement - manipuler dans Java Contexte de l'application de lot de printemps

J'ai essayé de fournir une instance configurée différente de XMLFriendlyNameCoder (en utilisant diverses implémentations de HierarchicalStreamDriver) ainsi que d'utiliser une implémentation complètement différente de NoNameCoder. Bien que l'application fonctionne avec succès, les résultats restent inchangés. J'utilise XStream 1.4.8. Il y a beaucoup d'exemples d'utilisation de la solution de contournement suggérée (en voici un couple, http://forum.spring.io/forum/spring-projects/batch/74500-getting-double-underscores-in-xml-when-using-staxeventitemwriter, XStream and underscores), donc je suis assez confiant que mes diverses tentatives ont été correctement configurées (mais je pourrais donner sur quelque chose). Voici ma configuration la plus récente:

<beans:bean id="myMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> 
    <beans:property name="streamDriver"> 
     <beans:bean class="com.thoughtworks.xstream.io.xml.Xpp3Driver"> 
      <beans:constructor-arg> 
       <beans:bean class="com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder"> 
        <beans:constructor-arg index="0" value="DDD"/> 
        <beans:constructor-arg index="1" value="_"/> 
       </beans:bean> 
      </beans:constructor-arg> 
     </beans:bean> 
    </beans:property>      
    <beans:property name="fieldAliases"> 
    <util:map id="aliases"> 
      <beans:entry key="com.billup.beans.Data.extData" value="ext_data"/> 
     </util:map> 
    </beans:property> 
</beans:bean> 

Je ne suis pas vraiment sûr, mais la question semble être que le printemps est de ne pas décrocher cette configuration pour une raison quelconque. Creuser à travers org.springframework.oxm.xstream.XStreamMarshaller il semble que streamDriver est seulement utilisé dans marshalOutputStream (et marshalWriter, appelé dans marshalOutputStream) alors peut-être que j'ai configuré cela de manière à ce que l'implémentation personnalisée soit ignorée et que le streamDriver par défaut soit utilisé ...

@Override 
protected void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException { 
    ContentHandler contentHandler = StaxUtils.createContentHandler(eventWriter); 
    marshalSaxHandlers(graph, contentHandler, null); 
} 

@Override 
protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException { 
    try { 
     marshal(graph, new StaxWriter(new QNameMap(), streamWriter)); 
    } 
    catch (XMLStreamException ex) { 
     throw convertXStreamException(ex, true); 
    } 
} 

@Override 
protected void marshalOutputStream(Object graph, OutputStream outputStream) throws XmlMappingException, IOException { 
    if (this.streamDriver != null) { 
     marshal(graph, this.streamDriver.createWriter(outputStream)); 
    } 
    else { 
     marshalWriter(graph, new OutputStreamWriter(outputStream, this.encoding)); 
    } 
} 

@Override 
protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler) 
     throws XmlMappingException { 

    SaxWriter saxWriter = new SaxWriter(); 
    saxWriter.setContentHandler(contentHandler); 
    marshal(graph, saxWriter); 
} 

@Override 
protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException { 
    if (this.streamDriver != null) { 
     marshal(graph, this.streamDriver.createWriter(writer)); 
    } 
    else { 
     marshal(graph, new CompactWriter(writer)); 
    } 
} 

/** 
* Marshals the given graph to the given XStream HierarchicalStreamWriter. 
* Converts exceptions using {@link #convertXStreamException}. 
*/ 
private void marshal(Object graph, HierarchicalStreamWriter streamWriter) { 
    try { 
     getXStream().marshal(graph, streamWriter); 
    } 
    catch (Exception ex) { 
     throw convertXStreamException(ex, true); 
    } 
    finally { 
     try { 
      streamWriter.flush(); 
     } 
     catch (Exception ex) { 
      logger.debug("Could not flush HierarchicalStreamWriter", ex); 
     } 
    } 
} 

Je me rends compte cette question semble unique et une portée limitée, mais les réponses peuvent faire la lumière sur la plus grande question de savoir comment la configuration correctement streamDriver dans le contexte de l'application (dans une application Spring Batch).

Remarque- J'utilise Spring 4 et Java 8.

Merci

Edit: J'ai aussi essayé d'utiliser la configuration suivante:

<beans:bean id="myMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> 
    <beans:property name="streamDriver"> 
     <beans:bean class="com.thoughtworks.xstream.io.xml.DomDriver"> 
      <beans:constructor-arg value="UTF-8"/> 
      <beans:constructor-arg> 
       <beans:bean class="com.thoughtworks.xstream.io.naming.NoNameCoder"/> 
      </beans:constructor-arg> 
     </beans:bean> 
    </beans:property>  
    <beans:property name="fieldAliases"> 
    <util:map id="aliases"> 
      <beans:entry key="com.billup.beans.Data.extData" value="ext_data"/> 
     </util:map> 
    </beans:property> 
</beans:bean> 

Répondre

1

Apparemment j'allais sur ce la mauvaise direction. Le ci-dessous semble fonctionner:

<beans:bean id="myMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> 
    <beans:property name="nameCoder"> 
     <beans:bean class="com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder"> 
      <beans:constructor-arg index="0" value="_-"/> 
      <beans:constructor-arg index="1" value="_"/> 
     </beans:bean> 
    </beans:property> 
    <beans:property name="fieldAliases"> 
     <util:map id="aliases"> 
      <beans:entry key="com.billup.beans.Data.extData" value="ext_data"/> 
     </util:map> 
    </beans:property> 
</beans:bean>