最近在使用Castor-xml生成XML时发现生成的格式不符合要求。
如要求生成以下格式的XML
<Signature> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod> <Reference URI=""> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod> <DigestValue>222</DigestValue> </Reference> </SignedInfo> <SignatureValue>123</SignatureValue> <KeyInfo> <KeyName>1234</KeyName> </KeyInfo> </Signature>
一开始觉得定义一个类及映射一下就可以的,但生成的XML会出现节点顺序错乱及重复节点的问题(对于含有属性的子节点)
先看错误的方法:
类定义:
public class H2010BhlBean implements Serializable { private static final long serialVersionUID = 1L; protected String canonicalizationMethodAlgorithm; protected String signatureMethodAlgorithm; protected String uri; protected String digestMethodAlgorithm; protected String digestValue; protected String signatureValue; protected String keyName; //以下还有get及set方法,略 }
映射文件定义:
<?xml version="1.0" encoding="UTF-8"?> <mapping> <description>收发货申报报文</description> <class name="com.eclink.ytcis.bhlbill.vo.BhlBillMap"> <map-to xml="Signature"/> <field name="canonicalizationMethodAlgorithm"> <bind-xml name="Algorithm" node="attribute" location="SignedInfo/CanonicalizationMethod"/> </field> <field name="signatureMethodAlgorithm"> <bind-xml name="Algorithm" node="attribute" location="SignedInfo/SignatureMethod"/> </field> <field name="uri"> <bind-xml name="URI" node="attribute" location="SignedInfo/Reference"/> </field> <field name="digestMethodAlgorithm"> <bind-xml name="Algorithm" node="attribute" location="SignedInfo/Reference/DigestMethod"/> </field> <field name="digestValue"> <bind-xml name="DigestValue" node="element" location="SignedInfo/Reference"/> </field> <field name="signatureValue"> <bind-xml name="SignatureValue" node="element"/> </field> <field name="keyName"> <bind-xml name="KeyName" node="element" location="KeyInfo"/> </field> </mapping>
生成后的结果是这样:
<?xml version="1.0" encoding="GBK"?> <Signature> <SignedInfo> <Reference URI=""> <DigestValue></DigestValue> </Reference> </SignedInfo> <SignatureValue></SignatureValue> <KeyInfo> <KeyName></KeyName> </KeyInfo> <SignedInfo> <CanonicalizationMethod Algorithm=""/> </SignedInfo> <SignedInfo> <SignatureMethod Algorithm=""/> </SignedInfo> <SignedInfo> <Reference> <DigestMethod Algorithm=""/> </Reference> </SignedInfo> </Signature>
上面的结果显然不符合要求的。
查了相关castor的资料,基本也没说到这一块。。于是对XML进行分析,出现问题是因为多层节点及节点下面有属性值的设置,按Castor的映射原理,试着把所有叶子节点的父节点定义成单独的类,并进行映射,问题得以解决。
正确如下:
<?xml version="1.0" encoding="UTF-8"?> <mapping> <description>收发货申报报文</description> <class name="com.eclink.ytcis.bhlbill.vo.BhlBillMap"> <map-to xml="Signature"/> <field name="canonicalizationMethodBean" type="com.eclink.ytcis.bhl.bean.CanonicalizationMethodBean"> <bind-xml name="CanonicalizationMethod" location="SignedInfo"/> </field> <field name="signatureMethodBean" type="com.eclink.ytcis.bhl.bean.SignatureMethodBean"> <bind-xml name="SignatureMethod" location="SignedInfo"/> </field> <field name="referenceBean" type="com.eclink.ytcis.bhl.bean.ReferenceBean"> <bind-xml name="Reference" location="SignedInfo"/> </field> <field name="signatureValue"> <bind-xml name="SignatureValue" node="element"/> </field> <field name="keyName"> <bind-xml name="KeyName" node="element" location="KeyInfo"/> </field> <include href="mapping/h2010BhlSignedInfo.xml"/> </mapping>
引用的h2010BhlSignedInfo.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <mapping> <description>H2010报文头Head info mapping</description> <class name="com.eclink.ytcis.bhl.bean.CanonicalizationMethodBean"> <field name="canonicalizationMethodAlgorithm"> <bind-xml name="Algorithm" node="attribute"/> </field> <field name="canonicalizationMethod"> <bind-xml name="" node="text"/> </field> </class> <class name="com.eclink.ytcis.bhl.bean.SignatureMethodBean"> <field name="signatureMethodAlgorithm"> <bind-xml name="Algorithm" node="attribute"/> </field> <field name="signatureMethod"> <bind-xml name="" node="text" /> </field> </class> <class name="com.eclink.ytcis.bhl.bean.ReferenceBean"> <field name="uri"> <bind-xml name="URI" node="attribute" /> </field> <field name="digestMethod"> <bind-xml name="" node="text" location="DigestMethod"/> </field> <field name="digestMethodAlgorithm"> <bind-xml name="Algorithm" node="attribute" location="DigestMethod"/> </field> <field name="digestValue"> <bind-xml name="DigestValue" node="element" /> </field> </class> </mapping>
实体对象
public class H2010BhlBean implements Serializable { private static final long serialVersionUID = 1L; protected CanonicalizationMethodBean canonicalizationMethodBean; protected SignatureMethodBean signatureMethodBean; protected ReferenceBean referenceBean; protected String signatureValue; protected String keyName; //get set方法略 }
其它关联的类
public class CanonicalizationMethodBean implements Serializable { private static final long serialVersionUID = 1L; private String canonicalizationMethodAlgorithm; private String canonicalizationMethod; /** * @return the canonicalizationMethodAlgorithm */ public String getCanonicalizationMethodAlgorithm() { return canonicalizationMethodAlgorithm; } /** * @param canonicalizationMethodAlgorithm the canonicalizationMethodAlgorithm to set */ public void setCanonicalizationMethodAlgorithm( String canonicalizationMethodAlgorithm) { this.canonicalizationMethodAlgorithm = canonicalizationMethodAlgorithm; } /** * @return the canonicalizationMethod */ public String getCanonicalizationMethod() { return canonicalizationMethod; } /** * @param canonicalizationMethod the canonicalizationMethod to set */ public void setCanonicalizationMethod(String canonicalizationMethod) { this.canonicalizationMethod = canonicalizationMethod; } }
public class SignatureMethodBean implements Serializable { private static final long serialVersionUID = 1L; private String signatureMethodAlgorithm; private String signatureMethod; /** * @return the signatureMethodAlgorithm */ public String getSignatureMethodAlgorithm() { return signatureMethodAlgorithm; } /** * @param signatureMethodAlgorithm the signatureMethodAlgorithm to set */ public void setSignatureMethodAlgorithm(String signatureMethodAlgorithm) { this.signatureMethodAlgorithm = signatureMethodAlgorithm; } /** * @return the signatureMethod */ public String getSignatureMethod() { return signatureMethod; } /** * @param signatureMethod the signatureMethod to set */ public void setSignatureMethod(String signatureMethod) { this.signatureMethod = signatureMethod; } }
public class ReferenceBean implements Serializable { private static final long serialVersionUID = 1L; private String uri; private String digestMethodAlgorithm; private String digestMethod; private String digestValue; /** * @return the uri */ public String getUri() { return uri; } /** * @param uri the uri to set */ public void setUri(String uri) { this.uri = uri; } /** * @return the digestMethodAlgorithm */ public String getDigestMethodAlgorithm() { return digestMethodAlgorithm; } /** * @param digestMethodAlgorithm the digestMethodAlgorithm to set */ public void setDigestMethodAlgorithm(String digestMethodAlgorithm) { this.digestMethodAlgorithm = digestMethodAlgorithm; } /** * @return the digestMethod */ public String getDigestMethod() { return digestMethod; } /** * @param digestMethod the digestMethod to set */ public void setDigestMethod(String digestMethod) { this.digestMethod = digestMethod; } /** * @return the digestValue */ public String getDigestValue() { return digestValue; } /** * @param digestValue the digestValue to set */ public void setDigestValue(String digestValue) { this.digestValue = digestValue; } }
映射后生成的结果:
<?xml version="1.0" encoding="GBK"?> <Signature> <SignedInfo> <CanonicalizationMethod> <CanonicalizationMethod Algorithm=""/> </CanonicalizationMethod> <SignatureMethod> <SignatureMethod Algorithm=""/> </SignatureMethod> <Reference> <Reference URI=""> <DigestMethod Algorithm=""/> <DigestValue></DigestValue> </Reference> </Reference> </SignedInfo> <SignatureValue></SignatureValue> <KeyInfo> <KeyName></KeyName> </KeyInfo> </Signature>
公共处理类:
package com.eclink.util; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; import org.xml.sax.InputSource; import sun.net.www.content.text.plain; import com.eclink.spring.ServiceFactory; import com.eclink.ytcis.workShop.vo.PactList; public class MarshallerUtil { /** * * @param cls * @param objectXml * @return * @throws Exception */ public static Object unmarshaller(@SuppressWarnings("rawtypes") Class cls, String objectXml) throws Exception { File f = new File(objectXml); return unmarshallerNew(cls, f, false); } /** * * @param cls * @param objectXml * @return * @throws Exception * @author XuChang */ @SuppressWarnings("rawtypes") public static Object unmarshaller(Class cls, File objectXml) throws Exception { return unmarshallerNew(cls, objectXml, false); } @SuppressWarnings("rawtypes") public static Object unmarshaller(Class cls, File objectXml, boolean namespace) throws Exception { Unmarshaller unmarshaller = ServiceFactory.getUnmarshaller(); unmarshaller.setClass(cls); if (namespace == true) { unmarshaller.setProperty("org.exolab.castor.parser.namespaces", "true"); } EncodingDetect detector = new EncodingDetect(); int codingValue = detector.detectEncoding(objectXml); String encoding = detector.getEncoding(codingValue); if ("OTHER".equals(encoding)) { encoding = Constants.XML_ENCODING; } Reader reader = new BufferedReader(new InputStreamReader( new FileInputStream(objectXml), encoding)); Object obj = (Object) unmarshaller.unmarshal(reader); reader.close(); return obj; } @SuppressWarnings("rawtypes") public static Object unmarshallerNew(Class cls, File objectXml, boolean namespace) throws Exception { Unmarshaller unmarshaller = ServiceFactory.getUnmarshaller(); unmarshaller.setClass(cls); if (namespace == true) { unmarshaller.setProperty("org.exolab.castor.parser.namespaces", "true"); } FileInputStream is = new FileInputStream(objectXml); byte[] b = new byte[(int) objectXml.length()]; is.read(b); is.close(); byte[] b2 = null; boolean isRepeat = false; if (b[0] == -17 && b[1] == -69 && b[2] == -65) { b2 = new byte[b.length - 3]; for (int i = 0, len = b2.length; i < len; i++) { b2[i] = b[i + 3]; } isRepeat = true; } else { b2 = b; } String content = new String(b2); int encodingIndex = content.indexOf("encoding=\""); String encoding = "UTF-8"; if (encodingIndex > 0) { int encodingEndIndex = content.indexOf("\"", encodingIndex + 10); encoding = content.substring(encodingIndex + 10, encodingEndIndex); } content = new String(b2, encoding); // 有命名空间,删除命名空间 if (content.indexOf("<ExchangeTableEntity>") < 0) { content = content.replaceAll("<ExchangeTableEntity.*?>", "<ExchangeTableEntity>"); isRepeat = true; } if (isRepeat) { FileOutputStream fo = new FileOutputStream(objectXml); fo.write(content.getBytes(encoding)); fo.close(); } Reader reader = new BufferedReader(new InputStreamReader( new FileInputStream(objectXml), encoding)); Object obj = (Object) unmarshaller.unmarshal(reader); reader.close(); return obj; } @SuppressWarnings("rawtypes") public static Object unmarshallerString(Class cls, String objectXml) throws Exception { Unmarshaller unmarshaller = ServiceFactory.getUnmarshaller(); unmarshaller.setClass(cls); int index = objectXml.indexOf("<CONTAINER_ID>"); if (!objectXml.substring(index + 14, index + 15).equals("<")) { objectXml = objectXml.replaceAll("<CONTAINER_ID>", "<CONTAINER_ID><ID>"); objectXml = objectXml.replaceAll("</CONTAINER_ID>", "</ID></CONTAINER_ID>"); } Object obj = (Object) unmarshaller.unmarshal(new InputSource( new StringReader(objectXml))); return obj; } @SuppressWarnings("rawtypes") public static Object unmarshaller(Class cls, byte[] b, boolean namespace) throws Exception { Unmarshaller unmarshaller = ServiceFactory.getUnmarshaller(); unmarshaller.setClass(cls); if (namespace == true) { unmarshaller.setProperty("org.exolab.castor.parser.namespaces", "true"); } String encoding = Constants.XML_ENCODING; Reader reader = new BufferedReader(new InputStreamReader( new ByteArrayInputStream(b), encoding)); Object obj = (Object) unmarshaller.unmarshal(reader); reader.close(); return obj; } /** * * @param cls * @param objectXml * @param mappingXml * @return * @throws Exception */ public static Object unmarshaller(String objectXml, String mappingXml) throws Exception { Unmarshaller unmarshaller = ServiceFactory.getUnmarshaller(); Mapping mapping = new Mapping(); mapping.loadMapping(mappingXml); EncodingDetect detector = new EncodingDetect(); int codingValue = detector.detectEncoding(new File(objectXml)); String encoding = detector.getEncoding(codingValue); if ("OTHER".equals(encoding)) { encoding = Constants.XML_ENCODING; } Reader reader = new BufferedReader(new InputStreamReader( new FileInputStream(objectXml), encoding)); unmarshaller.setMapping(mapping); Object obj = (Object) unmarshaller.unmarshal(reader); reader.close(); return obj; } public static void marshaller(Object marobject, String filename) throws Exception { File f = new File(filename); marshaller(marobject, f); } public static void marshaller(Object marobject, File filename) throws Exception { marshaller(marobject, filename, true); } public static void marshaller(Object marobject, File filename, boolean nameSpace) throws Exception { Marshaller marshaller = (Marshaller) ServiceFactory.getMarshaller(); Writer out = new PrintWriter(filename, Constants.XML_ENCODING); marshaller.setWriter(out); marshaller.setProperty("org.exolab.castor.indent", "true"); marshaller.setEncoding(Constants.XML_ENCODING); if (nameSpace == true) { marshaller.setProperty("org.exolab.castor.parser.namespaces", "true"); marshaller.setNamespaceMapping("xsi", Constants.XML_NAMESPACE_XSI); marshaller.setNamespaceMapping("xsd", Constants.XML_NAMESPACE_XSD); } marshaller.marshal(marobject); out.flush(); out.close(); } public static String marshallerString(Object marobject, boolean nameSpace) throws Exception { Marshaller marshaller = null; StringWriter sw = null; try { marshaller = (Marshaller) ServiceFactory.getMarshaller(); sw = new StringWriter(); marshaller.setWriter(sw); marshaller.setProperty("org.exolab.castor.indent", "true"); marshaller.setEncoding(Constants.XML_ENCODING); if (nameSpace == true) { marshaller.setProperty("org.exolab.castor.parser.namespaces", "true"); marshaller.setNamespaceMapping("xsi", Constants.XML_NAMESPACE_XSI); } marshaller.marshal(marobject); } catch (Exception e) { throw e; } finally { sw.flush(); sw.close(); } return sw.getBuffer().toString(); } /** * 生成xml回执文件 * @Title: writeXML * @param @param filePath 生成文件的路径, * @param @param fileName 生成文件的名称, * @param @param MappingPath maping文件的路径 * @param @param entryapplyBack 需要生成的实体类 * @return void * @throws */ public static void writeExportXML(String filePath,String fileName,String MappingPath,Object object)throws Exception{ StringWriter writer=null; PrintStream pw=null; try{ File dir=new File(filePath); if(dir.exists()==false){ dir.mkdirs(); } String file=filePath+File.separator+fileName; Mapping map = new Mapping(); map.loadMapping(MappingPath); writer= new StringWriter(); Marshaller marshaller = new Marshaller(writer); marshaller.setProperty("org.exolab.castor.indent", "true"); marshaller.setEncoding(Constants.XML_ENCODING); marshaller.setMapping(map); marshaller.marshal(object); writer.close(); pw=new PrintStream(new FileOutputStream(file),true,Constants.XML_ENCODING); pw.print(writer.toString()); } catch (IOException e) { e.printStackTrace(); throw new Exception("在生成xml回执文件的时候,打开文件流失败:"+e.getMessage()); } catch(Exception ex){ ex.printStackTrace(); throw new Exception("生成xml回执文件解析失败:"+ex.getMessage()); }finally{ if(writer!=null){ try { writer.close(); } catch (IOException e) { e.printStackTrace(); throw new Exception("在生成xml回执文件的时候,关闭文件流失败:"+e.getMessage()); } } if(pw!=null){ pw.flush(); pw.close(); } } } /** * @Title: writeXML * @Description: xml格式返回的字符串 * @param @param MappingPath maping文件的路径 * @param @param entryapplyBack 需要生成的实体类 * @return String xml格式返回的字符串 * @throws */ public static String writeXMLtoString(String MappingPath,Object object)throws Exception{ StringWriter writer=null; try{ Mapping map = new Mapping(); map.loadMapping(MappingPath); writer= new StringWriter(); Marshaller marshaller = new Marshaller(writer); marshaller.setProperty("org.exolab.castor.indent", "true"); marshaller.setEncoding(Constants.XML_ENCODING); marshaller.setMapping(map); marshaller.marshal(object); writer.close(); return writer.toString(); } catch (IOException e) { e.printStackTrace(); throw new Exception("在生成xml回执文件的时候,打开文件流失败:"+e.getMessage()); } catch(Exception ex){ ex.printStackTrace(); throw new Exception("生成xml回执文件解析失败:"+ex.getMessage()); }finally{ if(writer!=null){ try { writer.close(); } catch (IOException e) { e.printStackTrace(); throw new Exception("在生成xml回执文件的时候,关闭文件流失败:"+e.getMessage()); } } } } public static void writeExportXMLByString(String filePath,String fileName,String xmlContent) throws Exception{ StringWriter writer=null; PrintStream pw=null; try{ File dir=new File(filePath); if(dir.exists()==false){ dir.mkdirs(); } String file=filePath+File.separator+fileName; pw=new PrintStream(new FileOutputStream(file),true,Constants.XML_ENCODING); pw.print(xmlContent); } catch (IOException e) { e.printStackTrace(); throw new Exception("在生成xml回执文件的时候,打开文件流失败:"+e.getMessage()); } catch(Exception ex){ ex.printStackTrace(); throw new Exception("生成xml回执文件解析失败:"+ex.getMessage()); }finally{ if(writer!=null){ try { writer.close(); } catch (IOException e) { e.printStackTrace(); throw new Exception("在生成xml回执文件的时候,关闭文件流失败:"+e.getMessage()); } } if(pw!=null){ pw.flush(); pw.close(); } } } }
相关推荐
3. **使用Castor Mapping**:在Castor中,你需要通过XML映射文件(通常是`.xml`扩展名)来指定Java类和XML元素之间的对应关系。在这个映射文件中,定义根节点与Java顶级类的对应,并为其他类和元素设定映射规则。 4...
2. **处理复杂结构**:如果XML文档有复杂的嵌套结构,Castor能够自动处理这些关系,将XML节点转化为对应的Java对象,包括集合类、继承结构等。 **四、Castor的其他特性** 1. **类型转换**:Castor支持多种数据类型...
Castor是Java中一个强大的数据绑定框架,它允许开发者将XML文档与Java对象之间进行映射,从而实现XML数据的序列化和反序列化。在Java应用开发中,处理XML数据时,通常需要将XML文件内容转换为Java对象,或者将Java...
2. **对象-XML映射**:在Castor中,你可以定义一个类,然后使用注解或XML映射文件指定类的属性如何映射到XML元素。例如,类的属性可以对应XML文档中的节点,类的嵌套对象可以映射为子元素。 3. **序列化**:将Java...
- **Castor**:Castor提供了XML到Java对象的映射,支持复杂的数据结构,包括集合和嵌套对象。 - **XML Beans**:XML Beans是由Apache组织提供的,它允许开发者通过Java类型系统直接访问XML内容,同时支持XML ...
6. **性能优化**:Castor使用高效的缓存机制,对于重复解析的XML节点,能有效避免不必要的内存开销。 7. **灵活的映射策略**:用户可以选择使用XML映射文件或者注解来定义XML与Java对象之间的映射关系,满足不同...
5. **自动映射**:Castor提供自动映射功能,即根据Java类的名称和结构尝试自动创建XML映射。但这可能不适用于所有复杂情况,因此在某些情况下,需要自定义映射文件以确保精确的映射。 6. **集合和数组的映射**:在...
"春使用OXM进行对象XML映射解析" 春框架中使用OXM(Object-XML Mapping)对对象进行XML映射解析,具有一定借鉴价值。下面将详细介绍春使用OXM进行对象XML映射解析的技术要点。 1. 认识XML解析技术 XML...
尽管目前Java XML数据绑定还没有统一的标准接口,JSR-031正在努力推动这一进程,但Castor已经是一个成熟的解决方案,可用于立即开始开发。 总之,Castor框架是Java开发者处理XML数据的一个强大工具,它通过数据绑定...
- `Castor`:另一个强大的Java对象与XML数据绑定工具,支持XML到Java对象以及Java对象到XML的双向转换。 5. **XML与JSON对比**: - JSON通常被认为比XML更简洁,更适合网络传输,因为它的语法更接近编程语言,...
Castor是一个流行的Java库,专门用于对象关系映射(ORM)和XML绑定。在本案例中,Castor提供了将XSD文件转换为Java源代码(即JavaBean)的功能。使用Castor,开发者无需手动编写JavaBean类,只需提供XSD文件,Castor...
它使用直观的命名规则,使得XML映射过程更加简单。 10. 性能比较: - JAXB是Java标准,性能相对较好,适用于大量数据转换;DOM适合处理小到中等大小的XML文档,而SAX和StAX适用于处理大文件;其他第三方库如...
- DTD是用来定义XML文档结构和元素类型的规范,它规定了元素的名称、属性、出现次数等,确保XML文档符合特定的语法规则。 - DTD可以内嵌在XML文档中,也可以作为外部引用,提供了一种验证XML文档完整性和有效性的...
在Java中,有一种技术称为Java-XML绑定(如JAXB),它允许将XML文档直接映射为Java对象,反之亦然。不过,SAXReader不直接支持Java-XML绑定,但可以配合其他库(如Castor、XStream)实现此功能。例如,通过Castor库...
- JAXB(Java Architecture for XML Binding):提供了一种将Java对象映射为XML的机制,便于对象到XML的转换。使用`JAXBContext` 创建上下文,然后调用`marshal` 方法进行序列化。 3. XML修改 - DOM:通过DOM API...
另外,Spring框架中的`org.springframework.oxm`包提供了多种XML转换工具,如JAXB、Castor、XStream等,可以方便地进行XML与Java对象之间的转换。 总结起来,Java中的XML处理是一项重要的技能,涵盖DOM、SAX、StAX...
1. **Unmarshaller接口**:`Unmarshaller`接口定义了反序列化的基本操作,如`unmarshal`方法,将XML输入流或节点转换为Java对象。它的实现类如`Jaxb2Unmarshaller`会调用JAXB的相应API完成反序列化过程。 2. **...
同时,DOM4J还可以与其他Java库如XStream、Castor等配合,进行XML数据的序列化和反序列化。 总结,DOM4J作为Java处理XML的强大工具,提供了丰富的API和特性,使得XML的读写、操作和解析变得简单。无论是小型项目...