はじめまして。
素晴らしいものを公開していただき、ありがとうございます。
Tomcat6.0上のServletで、XQueryを処理するプログラムを書いているのですが、ちょっと困ったことが起きておりまして、ご相談する
次第です。
解決のためのヒントだけでもいただけたら幸いです。
このようなXML文書(<record>で括られるタプルが6600件程度)を、
<records xmlns:hoge="
http://www.hoge.jp/dtd">
<record hoge:id="1" id="046340" hoge:href="/aozora/sakuhin/1/">
<personid hoge:href="/aozora/sakuhin/1/personid">001234</personid>
<author hoge:href="/aozora/sakuhin/1/author">愛知 敬一</author>
<workid hoge:href="/aozora/sakuhin/1/workid">046340</workid>
<title hoge:href="/aozora/sakuhin/1/title">ファラデーの伝 電気学の泰斗</title>
<kanaknd hoge:href="/aozora/sakuhin/1/kanaknd">新字新仮名</kanaknd>
<transrator hoge:href="/aozora/sakuhin/1/transrator" />
<puncher hoge:href="/aozora/sakuhin/1/puncher">松本吉彦、松本庄八</puncher>
<proofreader hoge:href="/aozora/sakuhin/1/proofreader">小林繁雄</
proofreader>
<condition hoge:href="/aozora/sakuhin/1/condition">公開</condition>
<conditiondate hoge:href="/aozora/sakuhin/1/
conditiondate">2006-12-24</conditiondate>
<source hoge:href="/aozora/sakuhin/1/source">ファラデーの傳</source>
<publisher hoge:href="/aozora/sakuhin/1/publisher">岩波書店</publisher>
<edition hoge:href="/aozora/sakuhin/1/edition">1923(大正12)年5月15日第1版</
edition>
<proofedition hoge:href="/aozora/sakuhin/1/proofedition">1923(大正12)年5
月15日第1版</proofedition>
</record>
<record hoge:id="2" id="046511" hoge:href="/aozora/sakuhin/2/">
<personid hoge:href="/aozora/sakuhin/2/personid">001245</personid>
<author hoge:href="/aozora/sakuhin/2/author">会津 八一</author>
<workid hoge:href="/aozora/sakuhin/2/workid">046511</workid>
<title hoge:href="/aozora/sakuhin/2/title">一片の石</title>
<kanaknd hoge:href="/aozora/sakuhin/2/kanaknd">新字旧仮名</kanaknd>
<transrator hoge:href="/aozora/sakuhin/2/transrator" />
<puncher hoge:href="/aozora/sakuhin/2/puncher">門田裕志</puncher>
<proofreader hoge:href="/aozora/sakuhin/2/proofreader">仙酔ゑびす</
proofreader>
<condition hoge:href="/aozora/sakuhin/2/condition">公開</condition>
<conditiondate hoge:href="/aozora/sakuhin/2/
conditiondate">2007-01-03</conditiondate>
<source hoge:href="/aozora/sakuhin/2/source">日本の名随筆88 石</source>
<publisher hoge:href="/aozora/sakuhin/2/publisher">作品社</publisher>
<edition hoge:href="/aozora/sakuhin/2/edition">1996(平成8)年8月25日第5刷</
edition>
<proofedition hoge:href="/aozora/sakuhin/2/proofedition" />
</record>
...
</records>
以下のようなXQueryで、
declare namespace hoge="
http://www.hoge.jp/dtd";
<records xmlns:hoge="
http://www.hoge.jp/dtd">
{for $t in doc("data.xml")/records/record return
<record>{$t/@*}
{$t/author/text() }
{ fn:concat("《", $t/title/text() , "》") }
</record>
}
</records>
処理します。
期待される結果は、
<records xmlns:hoge="
http://www.hoge.jp/dtd">
<record hoge:id="1" id="046340" hoge:href="/aozora/sakuhin/1/">愛知 敬一
《ファラデーの伝 電気学の泰斗》</record>
<record hoge:id="2" id="046511" hoge:href="/aozora/sakuhin/2/">会津 八一
《一片の石》</record>
...
</records>
というような格好で、これは正常に結果が返りますが、ブラウザのリロードボタンを素早く何回も押すと、かなりの確率で
xbird.xquery.DynamicError: Writing SAX event failed
javax.xml.stream.XMLStreamException: Prefix hoge is already bound to
http://www.hoge.jp/dtd. Trying to rebind it to is an error.
at xbird.xquery.dm.ser.StAXSerializer.wrapStaxException
(StAXSerializer.java:129)
at xbird.xquery.dm.ser.StAXSerializer.evAttribute(StAXSerializer.java:
84)
at xbird.xquery.dm.ser.Serializer.evAttribute(Serializer.java:150)
at xbird.xquery.dm.instance.DocumentTableModel.export
(DocumentTableModel.java:325)
at xbird.xquery.dm.instance.DocumentTableModel.export
(DocumentTableModel.java:268)
at xbird.xquery.dm.ser.Serializer.evNode(Serializer.java:145)
at xbird.xquery.dm.ser.Serializer.emit(Serializer.java:123)
at xbird.xquery.dm.ser.Serializer.emit(Serializer.java:98)
at xbird.xquery.expr.AbstractXQExpression.evalAsEvents
(AbstractXQExpression.java:98)
at xbird.xquery.expr.opt.PathVariable.evalAsEvents(PathVariable.java:
107)
at xbird.xquery.expr.constructor.ElementConstructor.evalAsEvents
(ElementConstructor.java:293)
at xbird.xquery.expr.flwr.FLWRExpr.evalAsEvents(FLWRExpr.java:292)
at xbird.xquery.expr.constructor.ElementConstructor.evalAsEvents
(ElementConstructor.java:293)
at xbird.xquery.XQueryProcessor.execute(XQueryProcessor.java:172)
at xbird.xquery.XQueryProcessor.execute(XQueryProcessor.java:160)
at XBird.invokeQueryPushMode(XBird.java:68)
at XBird.doGet(XBird.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter
(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter
(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke
(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke
(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke
(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke
(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke
(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service
(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process
(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol
$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:
447)
at java.lang.Thread.run(Unknown Source)
Caused by: javax.xml.stream.XMLStreamException: Prefix hoge is already
bound to
http://www.hoge.jp/dtd. Trying to rebind it to is an error.
at
com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeAttribute
(Unknown Source)
at xbird.xquery.dm.ser.StAXSerializer.evAttribute(StAXSerializer.java:
82)
... 29 more
というようなことになります。
データ上に、xmlns:hoge="
http://www.hoge.jp/dtd" による属性値を記述してありますが、これを外すと上記のような
エラーは返りません。
長くなりますが、以下に呼び出し側の処理を貼ります。
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/xml");
Writer out = response.getWriter();
URI baseUri = null;
String query = "declare namespace hoge=\"
http://www.hoge.jp/dtd\";
<records xmlns:hoge=\"
http://www.hoge.jp/dtd\"> {for $t in doc
(\"data.xml\")/records/record return <record>{$t/@*}{$t/author/text() }
{ fn:concat(\"《\", $t/title/text() , \"》\") }</record>} </records>";
InputStream is = new ByteArrayInputStream(query.getBytes
("UTF-8"));
try {
invokeQueryPushMode(is, baseUri, out);
} catch (XQueryException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
private void invokeQueryPushMode(InputStream input, URI baseUri,
Writer writer) throws XQueryException, XMLStreamException {
XQueryProcessor proc = new XQueryProcessor();
XQueryModule module = proc.parse(input, baseUri);
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter streamWriter = factory.createXMLStreamWriter
(writer);
XQEventReceiver handler = new StAXSerializer(streamWriter);
proc.execute(module, handler);
streamWriter.flush();
}
なお、当然のことながらソースコード中のinvokeQueryPushMode()メソッドを synchronized で宣言すると、上記のよう
なエラーは発生しません。
実行環境は以下の通りです
・Windows Vista 6.0
・Java(TM) SE Runtime Environment 1.6.0_15-b03
・Apache Tomcat/6.0.18
よろしくお願いいたします。