Java で RESTFUL Web サービスを作成しています。アイデアは、XML ドキュメントを「削減」し、すべての不要なコンテンツ (~98%) を取り除き、関心のあるタグのみを残しながら、ドキュメントの構造を次のように維持することです (提供できません)。機密保持のため実際の XML コンテンツ):
<sear:SEGMENTS xmlns="http://www.exlibrisgroup.com/xsd/primo/primo_nm_bib" xmlns:sear="http://www.exlibrisgroup.com/xsd/jaguar/search">
<sear:JAGROOT>
<sear:RESULT>
<sear:DOCSET IS_LOCAL="true" TOTAL_TIME="176" LASTHIT="9" FIRSTHIT="0" TOTALHITS="262" HIT_TIME="11">
<sear:DOC SEARCH_ENGINE_TYPE="Local Search Engine" SEARCH_ENGINE="Local Search Engine" NO="1" RANK="0.086826384" ID="2347460">
[
<PrimoNMBib>
<record>
<display>
<title></title>
</display>
<sort>
<author></author>
</sort>
</record>
</PrimoNMBib>
]
</sear:DOC>
</sear:DOCSET>
</sear:RESULT>
</sear:JAGROOT>
</sear:SEGMENTS>
もちろん、これは関心のあるタグのみの構造です。他にも何百ものタグがありますが、それらは無関係です。
角かっこ ([]) は XML の一部ではなく、要素が子のリストの要素であり、複数回出現することを示します (RESTFUL サービスからの検索の一致ごとに 1 回)。
そうは言っても、XSLT スタイルシートを含む私の Java コードは次のとおりです。
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public String cutXML() throws TransformerFactoryConfigurationError, TransformerException
{
String xmlSourceResource = this.xml; // where this.xml is the full XML string of structure as presented above
String xsltResource =
"<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:sear=\"http://www.exlibrisgroup.com/xsd/jaguar/search\">" +
" <xsl:output method=\"xml\" version=\"1.0\" omit-xml-declaration=\"no\" encoding=\"UTF-8\" indent=\"yes\"/>" +
" <xsl:strip-space elements=\"*\"/>" +
" <sear:WhiteList>" +
" <name>title</name>" +
" <name>author</name>" +
" </sear:WhiteList>" +
" <xsl:template match=\"node()|@*\">" +
" <xsl:copy>" +
" <xsl:apply-templates select=\"node()|@*\"/>" +
" </xsl:copy>" +
" </xsl:template>" +
" <xsl:template match=\"*[not(descendant-or-self::*[name()=document('')/*/sear:WhiteList/*])]\"/>" +
"</xsl:stylesheet>";
StringWriter xmlResultResource = new StringWriter(); // where the transformed/stripped-down XML will be written
Transformer xmlTransformer = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader(xsltResource))); // create transformer object with XSLT given
xmlTransformer.transform(new StreamSource(new StringReader(xmlSourceResource)), new StreamResult(xmlResultResource)); // transform XML with transformer and write into result StringWriter
return xmlResultResource.getBuffer().toString(); // return transformed XML string
}
残念ながら、サーバー上で実行すると、変換の結果が空の文字列であるかのように、ソースが空の空のページしか得られません。
サーバーのログ ファイルは、最初に次の情報を提供しました。
[#|2012-04-26T18:26:24.967+0000|INFO|glassfish3.1.2|com.sun.jersey.api.core.PackagesResourceConfig|_ThreadID=23;_ThreadName=Thread-2;|Scanning for root resource and provider classes in the packages: dk.kb.mobileservice|#]
[#|2012-04-26T18:26:24.969+0000|INFO|glassfish3.1.2|com.sun.jersey.api.core.ScanningResourceConfig|_ThreadID=23;_ThreadName=Thread-2;|Root resource classes found: class dk.kb.mobileservice.Middle|#]
[#|2012-04-26T18:26:24.970+0000|INFO|glassfish3.1.2|com.sun.jersey.api.core.ScanningResourceConfig|_ThreadID=23;_ThreadName=Thread-2;|No provider classes found.|#]
[#|2012-04-26T18:26:24.978+0000|INFO|glassfish3.1.2|com.sun.jersey.server.impl.application.WebApplicationImpl|_ThreadID=23;_ThreadName=Thread-2;|Initiating Jersey application, version 'Jersey: 1.11 12/09/2011 10:27 AM'|#]
[#|2012-04-26T18:26:25.192+0000|INFO|glassfish3.1.2|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=23;_ThreadName=Thread-2;|WEB0671: Loading application [kb2] at [/kb2]|#]
[#|2012-04-26T18:26:25.200+0000|INFO|glassfish3.1.2|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|_ThreadID=23;_ThreadName=Thread-2;|kb2 was successfully deployed in 2,293 milliseconds.|#]
[#|2012-04-26T18:26:46.263+0000|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=20;_ThreadName=Thread-2;|SystemId Unknown; Line #0; Column #0; java.lang.NullPointerException |#]
[#|2012-04-26T18:31:09.772+0000|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=21;_ThreadName=Thread-2;|SystemId Unknown; Line #0; Column #0; java.lang.NullPointerException |#]
そして今、それは次の問題を返します:
[#|2012-04-27T00:05:07.731+0000|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=21;_ThreadName=Thread-2;|Error on line 1 column 1 of file:/root/webglassfish3/glassfish/domains/domain1/config/: SXXP0003: Error reported by XML parser: Content is not allowed in prolog.|#]
[#|2012-04-27T00:05:07.732+0000|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=21;_ThreadName=Thread-2;|Recoverable error on line 1 SXXP0003: org.xml.sax.SAXParseException: Content is not allowed in prolog.|#]
XML ファイルをテストし、ブラウザで変換したところ、うまくいきました。XML のせいでも、XSLT スタイルシートのせいでもないと思います... Java の問題のようです。
GlassFish の外部で XML 全体に対して上記の Java コードを実行すると、次のエラーが発生します。
Exception in thread "main" java.lang.VerifyError: (class: GregorSamsa$0, method: test signature: (IIIILcom/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;)Z) Incompatible type for getting or setting field
at GregorSamsa.applyTemplates()
at GregorSamsa.applyTemplates()
at GregorSamsa.transform()
at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.transform(AbstractTranslet.java:609)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:729)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:340)
at XML2JSON.cutXML(XML2JSON.java:105)
at XML2JSON.main(XML2JSON.java:31)