如何在JAVA中使用行号和列号获取XML中的元素 [英] How should I use line number and column number to get element in XML in JAVA

查看:81
本文介绍了如何在JAVA中使用行号和列号获取XML中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JAXB和元组/解组架构验证.我有一个XML文件和XSD架构用于验证.代码如下:

Hi I am using JAXB and Marshal/Unmarshal Schema Validation. I have a XML file and XSD schema for validation. Code are like this:

Validation.java

Validation.java

try{
    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = sf.newSchema(new File("./src/main/resources/validation.xsd"));
    JAXBContext jc = JAXBContext.newInstance(AddCustomer.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    unmarshaller.setSchema(schema);
    unmarshaller.setEventHandler(new MyValidationEventHandler());
    AddCustomer addCustomer_Validation= (AddCustomer) unmarshaller.unmarshal(new File("./src/main/resources/AddCustomer.xml"));
    logger.info("AddCustomer passed validation.");
} catch(UnmarshalException ex) {
    logger.info("linked ex: " + ex.getLinkedException().toString());
    String str = ex.getLinkedException().toString();
    int lineNumberIndex = str.indexOf("lineNumber:");
    int lineNumber = Integer.parseInt(str.substring(lineNumberIndex+12,lineNumberIndex+13));
    logger.info("lineNumber:" +lineNumber);
    int columnIndex = str.indexOf("columnNumber:");
    int columNumber = Integer.parseInt(str.substring(columnIndex+14,columnIndex+16));
    logger.info("columnNumber: " + columNumber);
}

一些XML文件是这样的:

Some of the XML file is like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AddCustomer xmlns="http://...">
<Customer>
    <DirectoryInformation>
        <PortalID>32        4   5</PortalID>
        <AccountID>2732</AccountID>

从上面的代码中,我可以验证XML对XSD是否有效.记录器文件如下所示:

From the code above, I could get validate the XML is valid against the XSD. The logger file is something like this:

INFO [main] Validation- linked ex: org.xml.sax.SAXParseException; systemId: file:/C:.../src/main/resources/AddCustomer.xml; lineNumber: 5; columnNumber: 41; cvc-pattern-valid: Value '32       4   5' is not facet-valid with respect to pattern '[ !-~]*' for type 'an..35'.
INFO [main] Validation- lineNumber: 5
INFO [main] Validation- columnNumber: 41

验证是正确的,并且在xml文件中,对于XSD架构,PortalID的值无效,日志文件可以告诉我位置是"lineNumber 5和ColumNumber 41",这正是PortalID的位置.

The validation is correct and in the xml file, the value of PortalID is not valid against the XSD schema, and the log file can tell me the location is "lineNumber 5 and ColumNumber 41" which is exactly the place for PortalID.

但是我想要使用此 lineNumber 5和ColumNumber41 打印出XML中的元素 PortalID 无效.有什么办法吗? 非常感谢!

But what I want is to use this lineNumber 5 and ColumNumber 41 to printout that the element PortalID in the XML is not valid. Is there any way to do that? Thank you so much!

推荐答案

要获取已解析的最后一个元素的名称,您可以放置​​一个自定义的ContentHandler,以记录SAXParser和JAXB处理程序之间的最后一个元素.

To get the name of the last element parsed you could put a custom ContentHandler that records the last element between the SAXParser and the JAXB handler.

为此,您必须使用 XMLFilter 实现扩展了 XMLFilterImpl

To do that you must use a SAXSource and create a custom XMLFilter implementation extending XMLFilterImpl

  1. SAXSource传递给Unmarshaller而不是File,并在SAXSource中配置XMLReader.在从javax.xml进行编组中对此进行了说明使用指定客户端验证SAX2.0解析器的.transform.sax.SAXSource
  2. 请勿像Javadoc链接代码中那样使用"real" XMLReader实现配置SAXSource,而是使用包装"real" XMLReader的自定义XMLFilter.

  1. pass a SAXSource to the Unmarshaller instead than a File and in the SAXSource configure an XMLReader. This is explained in Unmarshalling from a javax.xml.transform.sax.SAXSource using a client specified validating SAX2.0 parser
  2. Do not configure the SAXSource with the "real" XMLReader implementation as in Javadoc linked code but use the custom XMLFilter that wraps the "real" XMLReader.

   XMLReader xmlReader = saxParser.getXMLReader();
   RecordingXMLFilter xmlFilter = new RecordingXMLFilter(xmlReader);
   SAXSource source =
   new SAXSource(xmlFilter, new InputSource(new FileInputStream(new File("./src/main/resources/AddCustomer.xml")));

  • 自定义过滤器RecordingXMLFilter可能是:

  • The custom filter RecordingXMLFilter could be:

    private static final class RecordingXMLFilter extends XMLFilterImpl
    {
    
    String lastElement;
    
    private RecordingXMLFilter(XMLReader parent)
    {
        super(parent);
    }
    
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
    {
        lastElement = qName;
        super.startElement(uri, localName, qName, attributes);
    }
    }
    

  • 在异常处理代码中,使用xmlFilter.lastElement获取所解析的最后一个元素的QName.
  • In exception handling code use xmlFilter.lastElement to get the QName of the last element parsed.
  • 顺便说一句,要以这种方式获取行号,消息在不同的区域可能会有所不同,或者在版本之间会有所变化.

    BTW To get line numbers do in this way, messages could be different in different locales or change between versions.

        try
        {
            ..........
        }
        catch(UnmarshalException ex) {
            Throwable linked = ex.getLinkedException();
            if (linked instanceof SAXParseException)
            {
                SAXParseException t = (SAXParseException) linked;
                int lineNumber = t.getLineNumber();
                int columNumber = t.getColumnNumber();
                logger.info("lineNumber:" +lineNumber);
                logger.info("columnNumber: " + columNumber);
    
            }
        }
    

    这篇关于如何在JAVA中使用行号和列号获取XML中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆