我正在尝试从国会图书馆 Web 服务中提取书目数据,可以在此处看到生成的 xml 的示例。总而言之,它看起来像这样:
<zs:searchRetrieveResponse>
<zs:version>1.1</zs:version>
<zs:numberOfRecords>1</zs:numberOfRecords>
<zs:records>
<zs:record>
<zs:recordSchema>info:srw/schema/1/mods-v3.2</zs:recordSchema>
<zs:recordPacking>xml</zs:recordPacking>
<zs:recordData>
<mods version="3.2" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-2.xsd">
(Actual data I care about)
</mods>
</zs:recordData>
<zs:recordPosition>1</zs:recordPosition>
</zs:record>
</zs:records>
</zs:searchRetrieveResponse>
我使用 xmlbeans 编译 Java 客户端来读取“mods”标签内的数据,因为它有一个关联的模式。因此,本质上,我需要提取 mods 标记及其内容,并将其视为单独的 XML 文档。我可以使用正则表达式来做到这一点,但更喜欢真正的 XML 解决方案(“从不使用正则表达式解析 XML”,我不断听到)。我编写了以下 SSCCE 代码。
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class LibraryOfCongress {
public static void main(String[] args) throws XPathExpressionException,
ParserConfigurationException, SAXException, IOException {
String URL = "http://z3950.loc.gov:7090/voyager?operation=searchRetrieve&version=1.1&recordSchema=mods&maximumRecords=1&query=bath.isbn=0120502577";
HttpURLConnection conn = (HttpURLConnection) (new URL(URL))
.openConnection();
conn.setRequestMethod("GET");
int responseCode = conn.getResponseCode();
String document = null;
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader rd;
InputStream in = conn.getInputStream();
rd = new BufferedReader(new InputStreamReader(in));
String tempLine = rd.readLine();
StringBuilder response = new StringBuilder();
while (tempLine != null) {
response.append(tempLine).append("\n");
tempLine = rd.readLine();
}
document = response.toString();
rd.close();
}
if(document==null) return;
ByteArrayInputStream stream = new ByteArrayInputStream(document.getBytes());
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(stream);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath
.compile("/zs:searchRetrieveResponse/zs:records/zs:recordData");
Document ret = (Document) expr.evaluate(doc, XPathConstants.NODE);
if(ret!=null) {
String retval = ret.toString();
System.out.println(retval);
}
}
}
它什么也不做,因为 ret 为空。我尝试的变化:
1)
.compile("/");
...
String ret = (String) expr.evaluate(doc);
返回没有任何标签的文档。这是我能够解决的唯一输出,但当然我需要将标签传递给由 xmlbeans 生成的客户端。
2) 各种其他 XPath 查询字符串,但我无法获得指定根节点以外的任何内容的有用输出。
一些额外的担忧:
1)我读过 XPathConstants.NODE 仍然有某种对原始文档的引用,并且不会像我需要的那样生成独立的文档。不知道该怎么做,我认为拥有可独立解析的节点将是 XPath 的主要原因之一。
2) 我不知道如何处理 XPath 表达式中的命名空间。我只是猜测了一下。