【问题标题】:sax parser getting nex value for empty tagsax 解析器获取空标签的 nex 值
【发布时间】:2018-02-20 19:25:12
【问题描述】:

我试图用 sax 解析器获取 xm 的值,当标签为空时,就像解析器一样,而不是跳过该标签保存下一个标签的值,这是我的解析器:

public class HandlerRegistrarActa extends DefaultHandler {


    private RegistrarActaBeanReq acta = null;
    private List<Infracciones> infracciones = null;
    private Infracciones infraccion= null;

    public RegistrarActaBeanReq getActa() {
        return acta;
    }

    boolean bid_Acta = false;
    boolean bNro_Acta = false;
    boolean bLetra_Serie = false;
    boolean bInfraccion_Lugar = false;
    boolean bInfraccion_Numero = false;
    boolean bInfraccion_KmAltura = false;
    boolean bInfraccion_Referencia = false;
    boolean bInfraccion_Fec_Hora_Labrada = false;
    boolean bFec_Vencimiento = false;
    boolean bRetiene_Licencia = false;
    boolean bRetene_Vehiculo = false;
    boolean bTipoVehiculo = false;
    boolean bTipoPatente = false;
    boolean bConduccionPeligrosa = false;
    boolean bDominio = false;
    boolean bMarca = false;
    boolean bColor = false;
    boolean bSinTitular = false;
    boolean bTipo_Dni_Propietario = false;
    boolean bDni_propietario = false;
    boolean bNombre_Propietario = false;
    boolean bApellido_Propietario = false;
    boolean bRazon_Social_Propietario = false;
    boolean bCalle_propietario = false;


        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {

            if (qName.equalsIgnoreCase("id_Acta")) {
                bid_Acta = true;
                acta = new RegistrarActaBeanReq();
            } else if (qName.equalsIgnoreCase("Nro_Acta")) {
                bNro_Acta = true;
            } else if (qName.equalsIgnoreCase("Letra_Serie")) {
                bLetra_Serie = true;
            } else if (qName.equalsIgnoreCase("Infraccion_Lugar")) {
                bInfraccion_Lugar = true;
            } else if (qName.equalsIgnoreCase("Infraccion_Numero_Ruta")) {
                bInfraccion_Numero = true;
            } else if (qName.equalsIgnoreCase("Infraccion_KmAltura")) {
                bInfraccion_KmAltura = true;
            } else if (qName.equalsIgnoreCase("Infraccion_Referencia")) {
                bInfraccion_Referencia = true;
            } else if (qName.equalsIgnoreCase("Fec_Hora_Labrada")) {
                bInfraccion_Fec_Hora_Labrada = true;
            } else if (qName.equalsIgnoreCase("Fec_Vencimiento")) {
                bFec_Vencimiento = true;
            } else if (qName.equalsIgnoreCase("Retiene_Licencia")) {
                bRetiene_Licencia = true;
            } else if (qName.equalsIgnoreCase("Retiene_Vehiculo")) {
                bRetene_Vehiculo = true;
            } else if (qName.equalsIgnoreCase("TipoVehiculo")) {
                bTipoVehiculo = true;
            } else if (qName.equalsIgnoreCase("TipoPatente")) {
                bTipoPatente = true;
            } else if (qName.equalsIgnoreCase("ConduccionPeligrosa")) {
                bConduccionPeligrosa = true;
            } else if (qName.equalsIgnoreCase("Dominio")) {
                bDominio= true;
            } else if (qName.equalsIgnoreCase("Marca")) {
                bMarca = true;
            } else if (qName.equalsIgnoreCase("Color")) {
                bColor = true;
            } else if (qName.equalsIgnoreCase("SinTitular")) {
                bSinTitular = true;
            } else if (qName.equalsIgnoreCase("Tipo_Dni_Propietario")) {
                bTipo_Dni_Propietario = true;
            } else if (qName.equalsIgnoreCase("Dni_propietario")) {
                bDni_propietario = true;
            } else if (qName.equalsIgnoreCase("Nombre_Propietario")) {
                bNombre_Propietario = true;
            } else if (qName.equalsIgnoreCase("Apellido_Propietario")) {
                bApellido_Propietario = true;
            } else if (qName.equalsIgnoreCase("Razon_Social_Propietario")) {
                bRazon_Social_Propietario = true;
            } else if (qName.equalsIgnoreCase("Calle_propietario")) {
                bCalle_propietario = true;
            } 
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {

        }

        @Override
        public void characters(char ch[], int start, int length) throws SAXException {

            if (bid_Acta) {
                acta.setId_Acta(new String(ch, start, length).trim());
                bid_Acta = false;
            } else if (bNro_Acta) {
                acta.setNro_Acta(new String(ch, start, length).trim());
                bNro_Acta = false;
            } else if (bLetra_Serie) {
                acta.setLetra_Serie(new String(ch, start, length).trim());
                bLetra_Serie = false;
            } else if (bInfraccion_Lugar) {
                acta.setInfraccion_Lugar(new String(ch, start, length).trim());
                bInfraccion_Lugar = false;
            } else if (bInfraccion_Numero) {
                acta.setInfraccion_Numero_Ruta(new String(ch, start, length).trim());
                bInfraccion_Numero = false;
            } else if (bInfraccion_KmAltura) {
                acta.setInfraccion_KmAltura(new String(ch, start, length).trim());
                bInfraccion_KmAltura = false;
            }else if (bInfraccion_Referencia) {
                acta.setInfraccion_Referencia(new String(ch, start, length).trim());
                bInfraccion_Referencia = false;
            } else if (bInfraccion_Fec_Hora_Labrada) {
                acta.setFec_Hora_Labrada(new String(ch, start, length).trim());
                bInfraccion_Fec_Hora_Labrada = false;
            } else if (bFec_Vencimiento) {
                acta.setFec_Vencimiento(new String(ch, start, length).trim());
                bFec_Vencimiento = false;
            } else if (bRetiene_Licencia) {
                acta.setRetiene_Licencia(new String(ch, start, length).trim());
                bRetiene_Licencia = false;
            } else if (bRetene_Vehiculo) {
                acta.setRetene_vehiculo(new String(ch, start, length).trim());
                bRetene_Vehiculo = false;
            }else if (bTipoVehiculo) {
                acta.setTipo_Vehiculo(new String(ch, start, length).trim());
                bTipoVehiculo = false;
            } else if (bTipoPatente) {
                acta.setTipo_Patente(new String(ch, start, length).trim());
                bTipoPatente = false;
            } else if (bConduccionPeligrosa) {
                acta.setConduccion_Peligrosa(new String(ch, start, length).trim());
                bConduccionPeligrosa = false;
            } else if (bDominio) {
                acta.setDominio(new String(ch, start, length).trim());
                bDominio = false;
            } else if (bMarca) {
                acta.setMarca(new String(ch, start, length).trim());
                bMarca = false;
            }else if (bColor) {
                acta.setColor(new String(ch, start, length).trim());
                bColor = false;
            } else if (bSinTitular) {
                acta.setSinTitular(new String(ch, start, length).trim());
                bSinTitular = false;
            } else if (bTipo_Dni_Propietario) {
                acta.setTipo_Dni_Propietartio(new String(ch, start, length).trim());
                bTipo_Dni_Propietario = false;
            } else if (bDni_propietario) {
                acta.setDni_Propietario(new String(ch, start, length).trim());
                bDni_propietario = false;
            } else if (bNombre_Propietario) {
                acta.setNombre_Propietario(new String(ch, start, length).trim());
                bNombre_Propietario = false;
            }else if (bApellido_Propietario) {
                acta.setApellido_Propietario(new String(ch, start, length).trim());
                bApellido_Propietario = false;
            } else if (bRazon_Social_Propietario) {
                acta.setRazon_Social_Propietario(new String(ch, start, length).trim());
                bRazon_Social_Propietario = false;
            } else if (bCalle_propietario) {
                acta.setCalle_Propietario(new String(ch, start, length).trim());
                bCalle_propietario = false;
            } 
        }
    }

xml 我试图获取它的值:

<SDTActaCaminera xmlns='VialMza'><Acta>
<Id_Acta>1</Id_Acta>
<Nro_Acta>K0000000001</Nro_Acta>
<Letra_Serie>989</Letra_Serie>
<Infraccion_Lugar>RUTA NACIONAL</Infraccion_Lugar>
<Infraccion_Numero_Ruta>142</Infraccion_Numero_Ruta>
<Infraccion_KmAltura>10</Infraccion_KmAltura>
<Infraccion_Referencia>Aaa</Infraccion_Referencia>
<Fec_Hora_Labrada>20/02/2018 11:55:30</Fec_Hora_Labrada>
<Fec_Vencimiento>07/03/2018</Fec_Vencimiento>
<Retiene_Licencia>N</Retiene_Licencia>
<Retiene_Vehiculo>S</Retiene_Vehiculo>
<TipoVehiculo>AUTOMOVIL</TipoVehiculo>
<TipoPatente>AGF310</TipoPatente>
<ConduccionPeligrosa>S</ConduccionPeligrosa>
<Dominio>AGF310</Dominio>
<Marca>FIAT</Marca>
<Color>ROJO</Color>
<SinTitular>N</SinTitular>
<Tipo_Dni_Propietario>DNI</Tipo_Dni_Propietario>
<Dni_Propietario>31156986</Dni_Propietario>
<Nombre_Propietario>ANDRES</Nombre_Propietario>
<Apellido_Propietario>MARCOS</Apellido_Propietario>
<Razon_Social_Propietario></Razon_Social_Propietario>
<Calle_Propietario>AAA</Calle_Propietario>
</Acta>
</SDTActaCaminera>

您可以看到标签 razon_social_propietario 它是空的,而不是跳过该标签它保存下一个标签值(在本例中为 AAA)

【问题讨论】:

  • 请将其简化为minimal reproducible example - 我们无需费力地编写近 500 行代码。但是当你减少它时,如果你也让它 complete 会非常有帮助 - 让我们可以复制、编译和运行,使用 main 方法等。
  • 我只是减少代码,直到标签出现问题
  • 还是将近200行代码,还不完整。您应该将其减少到只是重现问题所需的内容,包括尽可能减少 XML 文件。
  • (从根本上说,你使用所有这些布尔值的方法对我来说似乎有问题。为什么不只保留最后遇到的元素名称?)
  • 另外,我建议在调用每个方法时添加诊断日志记录以及使用什么值。

标签: java xml saxparser


【解决方案1】:

你的代码当然是这样做的。

当您点击一个空标签时,会调用 startElementendElement,但不会调用 characters,因此当下一个元素点击时,您最终会设置 两个 标志。

我建议你去掉所有的标志,记住活动标签的名称,然后在endElement 中清除该名称。然后您在characters 中进行多路名称检查并根据需要进行分配。也会大大简化您的代码。

private RegistrarActaBeanReq acta = new RegistrarActaBeanReq();
private String activeName;

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    activeName = qName;
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    activeName = null;
}

@Override
public void characters(char ch[], int start, int length) throws SAXException {
    if (activeName == null)
        return;
    if (activeName.equalsIgnoreCase("id_Acta"))
        acta.setId_Acta(new String(ch, start, length).trim());
    else if (qName.equalsIgnoreCase("Nro_Acta"))
        acta.setNro_Acta(new String(ch, start, length).trim());
    else if ...
        ...
}

不过,我建议您改用 StAX 解析器。更容易使用。

【讨论】:

    【解决方案2】:

    问题可以分解为:

    public class HandlerRegistrarActa extends DefaultHandler {
        private RegistrarActaBeanReq acta = null;
        private boolean bRazon_Social_Propietario = false;
        private boolean bCalle_propietario = false;
    
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if (qName.equalsIgnoreCase("id_Acta")) {
                bid_Acta = true;
                acta = new RegistrarActaBeanReq();
            } else if (qName.equalsIgnoreCase("Razon_Social_Propietario")) {
                bRazon_Social_Propietario = true;
            } else if (qName.equalsIgnoreCase("Calle_propietario")) {
                bCalle_propietario = true;
            } 
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
    
        }
    
        public void characters(char ch[], int start, int length) throws SAXException {
    
            if (bRazon_Social_Propietario) {
                acta.setRazon_Social_Propietario(new String(ch, start, length).trim());
                bRazon_Social_Propietario = false;
            } else if (bCalle_propietario) {
                acta.setCalle_Propietario(new String(ch, start, length).trim());
                bCalle_propietario = false;
            } 
        }
    }
    

    使用以下 XML:

    <SDTActaCaminera xmlns='VialMza'>
        <Acta>
             <Razon_Social_Propietario></Razon_Social_Propietario>
             <Calle_Propietario>AAA</Calle_Propietario>
        </Acta>
    </SDTActaCaminera>
    

    这是您的最小、完整和可验证示例(或简短的 MCVE)。

    那么,如果有一个空标签会发生什么?
    不会为该元素调用 characters 方法。
    所以bRazon_Social_Propietario 将保留true。 并且下次调用 characters 时,它将使用它作为 Razon_Social_Propietario 的值。
    但它不再在那个标签中,而是在下一个标签中。

    要解决这个问题,您必须取消设置 endElement 中的布尔值:

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equalsIgnoreCase("Razon_Social_Propietario")) {
            bRazon_Social_Propietario = false;
        } else if (qName.equalsIgnoreCase("Calle_propietario")) {
            bCalle_propietario = false;
        }
    }
    

    我让你为所有属性实现这个。

    【讨论】:

      猜你喜欢
      • 2012-05-09
      • 2012-07-22
      • 2012-11-16
      • 2015-09-29
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 2013-01-02
      • 2011-02-19
      相关资源
      最近更新 更多