米国議会図書館の 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 が null であるため、何もしません。私が試したバリエーション:
1)
.compile("/");
...
String ret = (String) expr.evaluate(doc);
タグなしのドキュメントを返します。これは私が仕上げることができた唯一の出力ですが、もちろん、xmlbeans によって生成されたクライアントに渡すタグが必要です。
2) 他のさまざまな XPath クエリ文字列ですが、ルート ノード以外のものを指定して有用な出力を取得できません。
いくつかの追加の懸念事項:
1) XPathConstants.NODE にはまだ元のドキュメントへの何らかの参照があり、必要な独立したドキュメントを生成しないことを読みました。それについてどうすればよいかわかりませんが、独立して解析可能なノードを持つことが、XPath の主な理由の 1 つになると思います。
2) XPath 式で名前空間を処理する方法がわかりません。推測しただけです。