簡體   English   中英

如何在JAVA中使用行號和列號獲取XML中的元素

[英]How should I use line number and column number to get element in XML in JAVA

嗨,我正在使用JAXB和元組/解組架構驗證。 我有一個XML文件和XSD架構用於驗證。 代碼如下:

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文件是這樣的:

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

從上面的代碼中,我可以驗證XML對XSD是否有效。 記錄器文件是這樣的:

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文件中,PortalID的值對XSD架構無效,並且日志文件可以告訴我該位置是“ lineNumber 5和ColumNumber 41”,這正是PortalID的位置。

但是我想要的是使用此lineNumber 5和ColumNumber 41來打印出XML中的元素PortalID無效。 有什么辦法嗎? 非常感謝!

要獲取已解析的最后一個元素的名稱,可以放置一個自定義的ContentHandler,它記錄SAXParser和JAXB處理程序之間的最后一個元素。

為此,您必須使用SAXSource並創建擴展XMLFilterImpl的自定義XMLFilter實現。

  1. SAXSource傳遞給Unmarshaller而不是File並在SAXSource配置XMLReader 使用指定的驗證SAX2.0解析器的客戶端從javax.xml.transform.sax.SAXSource解組中對此進行了解釋。
  2. 不要像Javadoc鏈接代碼中那樣用“真正的” XMLReader實現配置SAXSource ,而是使用包裝“真正的” XMLReader的自定義XMLFilter。

      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"))); 
  3. 定制過濾器RecordingXMLFilter可以是:

     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); } } 
  4. 在異常處理代碼中,使用xmlFilter.lastElement獲取解析的最后一個元素的QName。

BTW要以這種方式獲取行號,消息在不同的區域可能會有所不同,或者在版本之間會有所不同。

    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);

        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM