当前位置: 首页 > 知识库问答 >
问题:

具有多个命名空间的 JAXB 编组和取消编组

缪修德
2023-03-14

我需要你在JAXB编组方面的帮助。这是关于命名空间的。我在这个令人惊叹的网站上阅读了不同的博客和很多答案,但我还没有意识到如何解决我的问题。

我需要用一些复杂的(至少对我来说)名称空间生成一个XML。

<?xml version="1.0" encoding="utf-8"?>
<cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd" version="3.2" fecha="2016-11-28T11:04:56" sello="MC7" formaDePago="una sola exhibición" noCertificado="00" certificado="MygA" subTotal="615.52" total="714.00" tipoDeComprobante="ingreso" LugarExpedicion="México DF" NumCtaPago="3138" TipoCambio="1.00" Moneda="MXN" metodoDePago="04" xmlns:cfdi="http://www.sat.gob.mx/cfd/3">
<cfdi:Emisor rfc="EMISOR" nombre="EMISOR">
<cfdi:DomicilioFiscal calle="SIN NUMERO" noExterior="na" municipio="México DF" estado="México" pais="MEX" codigoPostal="15620" />
<cfdi:ExpedidoEn calle="Calle" municipio="México" estado="México" pais="MEX" codigoPostal="63257" />
<cfdi:RegimenFiscal Regimen="GENERAL DE LEY PERSONAS MORALES" />
</cfdi:Emisor>
<cfdi:Receptor rfc="EMPRESA" nombre="EMPRESA">
<cfdi:Domicilio calle="Ave. Esclavitud No. 5300 " municipio="Mexico" pais="MEX" codigoPostal="52478" />
</cfdi:Receptor>
<cfdi:Conceptos>
<cfdi:Concepto cantidad="1.0000" unidad="no aplica" noIdentificacion="5213610219" descripcion="CONSUMO" valorUnitario="615.52" importe="615.52" />
</cfdi:Conceptos>
<cfdi:Impuestos totalImpuestosTrasladados="98.48">
<cfdi:Traslados>
<cfdi:Traslado impuesto="IVA" tasa="16.00" importe="98.48" />
</cfdi:Traslados>
</cfdi:Impuestos>
<cfdi:Complemento>
<tfd:TimbreFiscalDigital xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/TimbreFiscalDigital/TimbreFiscalDigital.xsd" version="1.0" UUID="070A8-5997-4F11-BCEE" FechaTimbrado="2016-11-28T11:05:05" selloCFD="MC7" noCertificadoSAT="20" selloSAT="In2" xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" />
</cfdi:Complemento>
<cfdi:Addenda xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://www.voxelgroup.net/xsd https://www.voxelgroup.net/xsd/addenda_v1.xsd" xmlns:voxel="https://www.voxelgroup.net/xsd">
   <voxel:AdditionalInfo>
   </voxel:AdditionalInfo>
</cfdi:Addenda>
</cfdi:Comprobante>

如您所见,该XML具有

< code > xmlns:xsi = " http://www . w3 . org/2001/XML schema-instance "

http://www.sat.gob.mx/cfd/3http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd

xmlns:cfdi="http://www.sat.gob.mx/cfd/3"

我做了不同的测试来解决这个问题,但没有成功。

您现在看到的java类是用xjc生成的(为了清晰起见,不是getter和setter):

        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {
            "informacionAduanera",
            "cuentaPredial",
            "complementoConcepto",
            "parte"
        })
        @XmlRootElement( name = "Comprobante", namespace = "http://www.sat.gob.mx/cfd/3")
        public static class Concepto {            
            @XmlElement(name = "InformacionAduanera")
            protected List<TInformacionAduanera> informacionAduanera;
            @XmlElement(name = "CuentaPredial")
            protected Comprobante.Conceptos.Concepto.CuentaPredial cuentaPredial;
            @XmlElement(name = "ComplementoConcepto")
            protected Comprobante.Conceptos.Concepto.ComplementoConcepto complementoConcepto;
            @XmlElement(name = "Parte")
            protected List<Comprobante.Conceptos.Concepto.Parte> parte;
            @XmlAttribute(name = "cantidad", required = true)
            protected BigDecimal cantidad;
            @XmlAttribute(name = "unidad", required = true)
            protected String unidad;
            @XmlAttribute(name = "noIdentificacion")
            protected String noIdentificacion;
            @XmlAttribute(name = "descripcion", required = true)
            protected String descripcion;
            @XmlAttribute(name = "valorUnitario", required = true)
            protected BigDecimal valorUnitario;
            @XmlAttribute(name = "importe", required = true)
            protected BigDecimal importe;
         }

这是package-info.class

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.w3.org/2001/XMLSchema-instance", 
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package mx.gob.sat.cfd._3;

我也有一个namespaceMapper:

public class MyNamespaceMapper extends com.sun.xml.bind.marshaller.NamespacePrefixMapper{

    private static final String CFDI_URI = "http://www.sat.gob.mx/cfd/3";
    private static final String CFDI_PREFIX = "cfdi";
    private static final String XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
    private static final String XSI_PREFIX = "";//xsi";
    private static final String SCHEMA_URI = "http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd";
    private static final String SCHEMA_PREFIX = "";//schemaLocation";

    @Override
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requiredPrefix) {
        switch(namespaceUri){
            case CFDI_URI:{ return CFDI_PREFIX; }
            case XSI_URI:{ return XSI_PREFIX; }
            case SCHEMA_URI:{ return SCHEMA_PREFIX; }
            default: { return ""; }
        }
    }
}

接下来,这是我得到的输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cfdi="http://www.sat.gob.mx/cfd/3" NumCtaPago="" LugarExpedicion="MEXICO" metodoDePago="02" tipoDeComprobante="ingreso" total="4000.00" Moneda="PESO" TipoCambio="1.0000" motivoDescuento="" descuento="0" subTotal="4000" condicionesDePago="EN UNA SOLA EXHIBICION" certificado="" noCertificado="00009200" formaDePago="CHEQUE" sello="" fecha="2016-12-02T12:40:42.302-06:00" folio="9" serie="A" version="3.2">
<xsi:Emisor nombre="PEPITO" rfc="PEPE">
<xsi:DomicilioFiscal codigoPostal="51890" pais="México" estado="México" municipio="México" colonia="México" noInterior="" noExterior="5300" calle="Esclavitud"/>
   <xsi:RegimenFiscal Regimen="Regimen General de Ley Personas Morales"/>
</xsi:Emisor>
<xsi:Receptor nombre="EMPRESA" rfc="EMPRESA">
  <xsi:Domicilio codigoPostal="51890" pais="México" estado="México" municipio="México" colonia="México" noInterior="" noExterior="5300" calle="Esclavitud"/>
</xsi:Receptor>
<xsi:Conceptos>
   <xsi:Concepto importe="4000" valorUnitario="4000" descripcion="ARRENDAMIENTO DEL MES DE SEPTIEMBRE" unidad="N/A" cantidad="1"/>
</xsi:Conceptos>
  <xsi:Impuestos>
   <xsi:Traslados>
      <xsi:Traslado importe="400" tasa="10" impuesto="ISR"/>
    </xsi:Traslados>
  </xsi:Impuestos>
</cfdi:Comprobante>

这是我从原始xml格式结束的。我尝试了不同的方法,但我没有更多的东西。

如您所见,在输出中仍然缺少第三个名称空间,

xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd"

并且每一行必须具有前缀cfdi而不是xsi。

我真的非常感谢任何完成这项工作的线索。

谢谢大家!

共有2个答案

傅旺
2023-03-14

也许太晚了,但我有这样的事情:

...
private Map<String, String> prefijos = new HashMap<String, String>();
prefijos.put("http://www.w3.org/2001/XMLSchema-instance","xsi"); 
prefijos.put("http://www.sat.gob.mx/cfd/3", "cfdi");
prefijos.put("http://www.sat.gob.mx/TimbreFiscalDigital", "tfd");
JAXBContext jaxbContext = JAXBContext.newInstance("mx.gob.sat.v33");
marshaller = jaxbContext.createMarshaller();

marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new 
NamespacePrefixMapperImpl(prefijos));
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,"http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd");

DocumentBuilderFactory docBuilderFac = DocumentBuilderFactory.newInstance();
docBuilderFac.setNamespaceAware(true);
DocumentBuilder db = null;
db = docBuilderFac.newDocumentBuilder();
Document doc = db.newDocument();
marshaller.marshal(comprobante,doc);
...

My NamespacePrefix MapperImpl是这样的:

public class NamespacePrefixMapperImpl extends NamespacePrefixMapper{
    private final Map<String, String> map;

    public NamespacePrefixMapperImpl(Map<String, String> map) {
        this.map = map;
    }

    public String getPreferredPrefix(String namespaceUri, String suggestion, 
                                               boolean requirePrefix) {
        String value = map.get(namespaceUri);
        return (value != null) ? value : suggestion;
    }

    public String[] getPreDeclaredNamespaceUris() {
        return new String[0];
    }
}

也许你可以看看这个项目

丁嘉庆
2023-03-14

如本示例所示,使用@XmlNs注释来自定义NS前缀。

例如

   @javax.xml.bind.annotation.XmlNs(prefix = "myns",
               namespaceURI="http://myns/schema"

这些例子会给你更多的背景知识。

即使您可以让RI类实现您想要的功能,使用API也比入侵仅实现类要好。

 类似资料:
  • 我有一个XML要与JAXB解组。如果我从元素中删除所有名称空间属性,代码运行良好,但是如果我保留名称空间属性的话,在解组后会得到一个空对象。 XML是这样的: 我的动物豆是这样的: 猫豆就像: 在运行时,我得到一个空对象。我试图从属性中删除< code>"z:",得到了这个异常: 如果我从猫和动物中删除命名空间,我会得到这个例外: 下面是解组的最终代码。最后一行给出了一个空指针异常 我不确定如何处

  • 我的代码如下: 我怎样才能让它工作?如果我的xml标记有一些相关元素,如上面的“xmlns”,则JAXB解组器会抛出异常。 这是我第一次这么做,所以我对JAXB、解编等都一无所知。我在苦苦挣扎任何帮助都是好的。 编辑StackTrace:

  • 这是我的xml,需要把它转换成Java。我使用了jaxb 并抛出以下异常javax.xml.bind.unmarshalException:意外元素(URI:“http://www.ae.com/event/load”,local:“order”)。需要的元素为<{}LM:order>

  • 我有几个关于JAXB编组的简单问题。我正在尝试封送包含以下字段的类: 只需使用以下序列化代码: 我得到的输出是: 现在,我面临的问题如下: > 我想要名称空间xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“出现在根元素中,即TokenRestrictionTemplate中,而不是单个子元素中。如何实现这一点? 我有一些元素,例如带有@Xm

  • 我正在使用 JAXB 来对我正在实现 Java 客户端的 Web 服务进行封送和解组和取消马歇尔请求和响应。然而,我被困在以下回应上,我需要解体。 为了将响应表示为Java对象,我有以下域类: 然后,我执行以下操作来解除元帅: 解编组没有发生任何事件。 对象是使用两个列表创建的。为空,有一项。但是,该项目上的和 null。我认为这与XML命名空间有关,但我无法弄清楚如何修复它。 我尝试了另一种方式

  • 我刚开始在xml中使用名称空间,所以我有点困惑,希望得到一些澄清。我有一个java服务,我正在接收具有许多不同名称空间的xml文档,当我开始工作时,我觉得我肯定做错了什么,所以我想检查一下。在我的包裹信息中。java我有我的模式注释,例如: 我有一辆火车.java在班级级别上注释如下: 并且类中的每个字段都注释为: 列车包含乘客列表,因此有一个属性 并且该集合被注释为: 然后在乘客体内。java类