如何使用Xpath从包含多个xml声明的xml文件中提取数据

时间:2017-10-30 10:56:50

标签: java xml xpath

我从在线资源获得了一个xml文件,这是一个名为MetaMap的程序的结果输出,它将生物医学文本映射到一个名为UMLS®Metathesaurus的语料库中的概念。原始的xml文件相当复杂,所以我刚刚列出了一小部分信息。每个<PMID>代表一篇生物医学文章 并<UttText>存储该文章中的一些句子。 <MMO>存储一篇文章的信息。

但正如您从文件中看到的那样,它有许多xml文件,每个文件都以 <?xml version="1.0" encoding="UTF-8"?>仅存储一篇文章的信息 - <MMO>下只有一个<MMOS>

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE MMOs PUBLIC "-//NLM//DTD MetaMap Machine Output//EN"
        "http://metamap.nlm.nih.gov/DTD/MMOtoXML_v5.dtd">

     <MMOs>
      <MMO>

       <PMID>000001</PMID>
       <UttText>abcdefg</UttText>  

      </MMO>
     </MMOs>

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE MMOs PUBLIC "-//NLM//DTD MetaMap Machine Output//EN" "http://metamap.nlm.nih.gov/DTD/MMOtoXML_v5.dtd">

     <MMOs>
      <MMO>

       <PMID>000002</PMID>
       <UttText>higklm</UttText>  

      </MMO>
     </MMOs>

现在我只尝试选择一条记录的代码 - 名为 a1.xml

 <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE MMOs PUBLIC "-//NLM//DTD MetaMap Machine Output//EN"
            "http://metamap.nlm.nih.gov/DTD/MMOtoXML_v5.dtd">

         <MMOs>
          <MMO>

           <PMID>000001</PMID>
           <UttText>abcdefg</UttText>  

          </MMO>
         </MMOs>

使用以下java代码对其执行Xpath查询:

package MBR;

import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
import javax.xml.xpath.XPath;  
import javax.xml.xpath.XPathConstants;  
import javax.xml.xpath.XPathExpression;  
import javax.xml.xpath.XPathFactory;  

import org.w3c.dom.Document;  
import org.w3c.dom.NodeList;  

public class MappedMBR {

        public static void main(String[] args) throws Exception {  
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
            factory.setNamespaceAware(true);  
            DocumentBuilder builder = factory.newDocumentBuilder();  
            Document doc = builder.parse("src/a1.xml");  

            XPathFactory pathFactory = XPathFactory.newInstance(); 
            XPath xpath = pathFactory.newXPath();
            XPathExpression pathExpression = xpath.compile("//PMID/text() | //UttText/text()"); 

            Object result = pathExpression.evaluate(doc, XPathConstants.NODESET);  

            NodeList nodes = (NodeList) result;  
            for (int i = 0; i < nodes.getLength(); i++) {  
                    System.out.println(nodes.item(i).getNodeValue());  
    }
        }
}

XPath是否有任何方法可以识别一个文件中的每个根元素,还是应该删除除文件中第一个之外的所有其他xml声明和根元素<MMOs>?如果是这样,如何在java中实现它?

1 个答案:

答案 0 :(得分:0)

你做不到。你正在处理的不是一个XML文件,它连接了几个XML文件。尝试使用它就像一个XML文件一样无法使用。

由于它是几个XML文件,最好的办法是使其成为多个XML文件,而不是将其保存在一个文件中。

您可以尝试以完全兼容的方式完成此操作,方法是利用XML读取器接口,这些接口可以随时读取标记,然后将它们写回新文件,然后检测根元素关闭标记何时发生,并处理底层BufferedReader进入下一个XML声明,从而以相同的方式处理下一个文档。

或者您可以将整个文件作为String加载到内存中,并通过XML声明拆分()。稍微不那么可靠,因为可以在XML文档中添加类似于XML声明的内容,但这不太可能发生,并且这种方法更简单。