getNodeName,getLocalName不返回预期值

时间:2016-10-10 14:30:13

标签: java xml parsing xml-namespaces

我正在解析一个简单的XML并尝试获取nodeNames。在此XML的某些变体中,某些nodeNames具有名称空间前缀" mets:"。我试图匹配所有" fptr"元素,无论它们是否具有mets-prefix。

这是xml的一个示例,包含简单的fptr元素和一些带有前缀的元素:

df <- sqlQuery(db, "select FileName, Version, Category, Value, Date, TestNum 
               from Table where Comments != 'Do Not Include in R Chart'",
               stringsAsFactors = F)

这是一个简单的解析例程,应该打印出所有元素的元素名称和ns前缀:

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

这是打印出来的:

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("");
            } 
        }
    }
}

所有前缀值均为空。我期望前两个fptr前缀(ID = DTL21和DTL22)是&#34; mets&#34;。

与localName相同:我希望所有的fptr-localNames都是&#34; fptr&#34;而不是它们都是null。与namespace-URI类似。

我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

确保在尝试以有意义的方式使用带有名称空间的XML之前设置dbFactory.setNamespaceAware(true);

答案 1 :(得分:1)

XML命名空间是非常明智的,就像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)));
}