0

米国議会図書館の 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 式で名前空間を処理する方法がわかりません。推測しただけです。

4

1 に答える 1

1

名前空間を持つ XML に対して XPath を使用する場合DocumentBuilderhttp://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/DocumentBuilderFactory.html#setNamespaceAware%28boolean%29DocumentBuilderFactory. 次に、NamespaceContext を実装する必要がある名前空間を使用して XPath 式を適用するには、マークがコメントでそれを示すページに既にリンクしていると思います。

XPath を使用して新しいドキュメントを選択することに関しては、いいえ、それは XPath が行うことではありません。これにより、既存のドキュメント内のノードを選択してナビゲートできるため、階層内で特定のノードを選択すると、そのノードが取得されますが、そのノードはすべての子と子孫、および祖先と兄弟とともにドキュメント内に残ります。

したがって、新しいスタンドアロン ドキュメントを作成する場合は、DocumentBuilder とhttp://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/DocumentBuilder.html#newDocumentを使用してドキュメントを作成する必要があります。 %28%29そして、入力ドキュメントで XPath を使用して選択したものを、最後importNodeに.adoptNodeappendChild

于 2013-11-10T10:56:50.273 に答える