2016-10-10 158 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 –

相关问题