2016-10-10 56 views
0

我解析一個簡單的XML並嘗試獲取nodeNames。在此XML的某些變體中,某些nodeNames具有名稱空間前綴「mets:」。我試圖匹配所有「fptr」元素,不管它們是否有一個mets-prefix。getNodeName,getLocalName不返回期望值

這裏是XML的例子,同時包含簡單FPTR元素和一些前綴:

<mets:structMap xmlns:mets="http://www.loc.gov/METS/" xmlns="http://www.loc.gov/METS/" TYPE="logical" ID="DTL1"> 
    <div ORDER="1" LABEL="Alle Scans" TYPE="first level" ID="DTL2"> 
     <div ORDER="1" LABEL="1" TYPE="Seite" ID="DTL3"> 
      <mets:fptr FILEID="FID00000020" ID="DTL21"/> 
     </div> 
     <div ORDER="2" LABEL="2" TYPE="Seite" ID="DTL4"> 
      <mets:fptr FILEID="FID00000021" ID="DTL22"/> 
     </div> 
    </div> 

    <div ORDER="1" LABEL="Hauptdokument - pdf" TYPE="entry" ID="DTL5"> 
     <fptr FILEID="FID1a" ID="DTL11"/> 
    </div> 
</mets:structMap> 

而且這裏有一個簡單的解析程序應打印出的元素名稱和所有元素的NS-前綴:

package at.ac.onb.zid.dtlcontent.test; 

import java.io.File; 
import java.io.IOException; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 

import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
import org.xml.sax.SAXException; 

public class structMapTest { 
    public static void main(String args[]) throws ParserConfigurationException, SAXException, IOException { 
     File fXmlFile = new File("src/test/resources/teststructmap.xml"); 
     DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 
     Document doc = dBuilder.parse(fXmlFile); 
     doc.getDocumentElement().normalize(); 

     NodeList elemList = doc.getElementsByTagName("*"); 
     for(int i = 0; i<elemList.getLength();i++) { 
      Node n = elemList.item(i); 
      System.out.println("nodeName=" + n.getNodeName()); 

      if(n instanceof Element) { 
       Element e = (Element) n; 
       String eID = e.getAttribute("ID"); 
       String nsPrefix = e.getPrefix(); 
       String eLN = e.getLocalName(); 
       String eNSURI = e.getNamespaceURI(); 

       System.out.println(" ID=" + eID); 
       System.out.println(" prefix=" + nsPrefix); 
       System.out.println(" localName=" + eLN); 
       System.out.println(" nsURI=" + eNSURI); 
       System.out.println(""); 
      } 
     } 
    } 
} 

這是它打印出來,但:

nodeName=mets:structMap 
    ID=DTL1 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL2 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL3 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=mets:fptr 
    ID=DTL21 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL4 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=mets:fptr 
    ID=DTL22 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL5 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=fptr 
    ID=DTL11 
    prefix=null 
    localName=null 
    nsURI=null 

一前綴值爲空。我預計前兩個fptr前綴(ID = DTL21和DTL22)是「mets」。

與localName相同:我期望所有fptr-localNames都是「fptr」,而不是全部爲空。類似於命名空間-URI。

我在這裏錯過了什麼?

回答

1

確保在嘗試以有意義的方式處理帶有名稱空間的XML之前設置了dbFactory.setNamespaceAware(true);

+0

非常感謝。我懷疑像這樣的事情,但甚至不知道從哪裏開始看......解決了它。 – jackthehipster

1

XML名稱空間是非常明智的,就像許多XML設計一樣,事實上像大部分XML設計在代碼中直接處理時都會是一個真正的痛苦。在你的例子中,前綴和非前綴元素實際上是相同的名稱空間URL,所以你根本不應該有任何問題。

Java 8庫Dynamics默認情況下忽略命名空間(但如果需要可以是顯式的,即在實際情況極少的情況下)。這個庫不是一種查詢語言,只是處理動態結構的一種非常直接的方式。由於這種遞歸很容易,所以我們可以這樣掃描所有元素:

{ 
    XmlDynamic example = new XmlDynamic(xmlStringOrReaderOrInputSourceEtc); 

    List<String> ids = allElements(example) 
     .filter(hasElementName("fptr")) // import static alexh.weak.XmlDynamic.hasElementName; 
     .map(fptr -> fptr.get("@ID").asString()) 
     .collect(toList()); 
    // [DTL21, DTL22, DTL11] 
} 

/** recursively stream all elements */ 
Stream<Dynamic> allElements(Dynamic root) { 
    return Stream.concat(Stream.of(root), root.children().flatMap(child -> allElements(child))); 
} 
+0

聽起來很有趣。你寫了那個庫嗎? – jackthehipster

+0

@jackthehipster是的。它實際上是一個用於處理嵌套弱類型數據的通用庫,XmlDynamic是XML的專用實現。如果您對源代碼和文檔感興趣,請參閱github https://github.com/alexheretic/dynamics#xml-dynamics –