2012-08-17 48 views
1

我必須編寫一些代碼來處理讀取和驗證在其根元素中使用version屬性來聲明版本號的XML文檔,如下所示:解決使用具有版本屬性的XML文檔的XML Schema版本

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<Junk xmlns="urn:com:initech:tps" 
    xmlns:xsi="http://www3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="urn:com:initech.tps:schemas/foo/Junk.xsd" 
    VersionAttribute="2.0"> 

還有一堆嵌套模式,我的代碼中有一個org.w3c.dom.ls.LsResourceResolver找出使用的模式,實施該方法:

LSInput resolveResource(String type, 
         String namespaceURI, 
         String publicId, 
         String systemId, 
         String baseURI) 

上的架構版本的嵌入式架構的版本爲命名空間,所以我可以使用namespaceURI和systemId來決定提供哪個模式。現在,版本號已切換到根元素中的屬性,並且我的解析器無法訪問該屬性。我該如何弄清LsResourceResolver中XML文檔的版本?

回答

3

我從來沒有必須在此之前處理模式版本,並不知道涉及到什麼。當版本是命名空間的一部分時,我可以將所有模式放在一起並讓它們整理出來,但是在根元素中的版本和在版本中共享的命名空間中,不會從XML讀取版本信息之前開始SAX解析。

我打算做一些非常類似於Pangea建議的東西(從我得到+1),但我無法完全遵循這個建議,因爲文檔太大而無法全部讀入內存,甚至一次。通過使用STAX,我可以最大限度地減少從文件中獲取版本的工作量。看到這個developerWorks文章,"Screen XML documents efficiently with StAX"

篩選或XML文檔的分類是一個常見的問題, 尤其是在XML的中間件。將XML文檔路由到特定的 處理器可能需要分析文檔類型和 文檔內容。這裏的問題是以儘可能少的開銷從文檔中獲取所需的 信息。 傳統分析器(如DOM或SAX)不適合此 任務。例如,DOM在將控制權返回給客戶端之前,解析整個文檔並在內存中構造一個完整的文檔樹。即使使用延遲節點擴展的DOM解析器,並且因此 也能夠部分解析文檔,具有高資源需求 ,因爲文檔樹必須至少部分地在 存儲器中構建。這對於篩選目的來說是不可接受的。

的代碼來獲取版本信息會看起來像:

def map = [:] 
def startElementCount = 0 
def inputStream = new File(inputFile).newInputStream() 
try { 
    XMLStreamReader reader = 
     XMLInputFactory.newInstance().createXMLStreamReader(inputStream) 
    for (int event; (event = reader.next()) != XMLStreamConstants.END_DOCUMENT;) { 
     if (event == XMLStreamConstants.START_ELEMENT) { 
      if (startElementCount > 0) return map 
      startElementCount += 1 
      map.rootElementName = reader.localName 
      for (int i = 0; i < reader.attributeCount; i++) { 
       if (reader.getAttributeName(i).toString() == 'VersionAttribute') { 
        map.versionIdentifier = reader.getAttributeValue(i).toString() 
        return map 
       } 
      } 
     } 
    } 
} finally { 
    inputStream.close() 
} 

然後,我可以使用的版本信息,以確定用什麼解析器,什麼模式文檔對SaxFactory設置。

3

我的建議

  1. 使用SAX或DOM
  2. 獲取的版本屬性
  3. 使用Validator.validate(來源)方法和解析文檔和使用已經被解析文檔(步驟1)如下圖所示

建築DOMSource的從分析的文檔

DocumentBuilder builder = factory.newDocumentBuilder(); 
Document document = builder.parse(new File(args[0])); 

domSource = new DOMSource(document); 
+0

有趣的建議。這是否需要將整個文檔讀入內存? – 2012-08-17 14:08:13

+0

@NathanHughes是的,但我相信你只做了一次。 – 2012-08-17 14:12:53