org.jdom.input.SAXBuilder を使用して、入力ストリーム (XML ファイル) を JDOM ドキュメントに解析しています。
SAXBuilder builder = new SAXBuilder(JavaScriptParser.class.getName());
org.jdom.Document document = builder.build(stream);
XML ストリームに特定のタグがあり、タグ内のコンテンツを CDATA として扱う必要があります。
例:
<text><![CDATA[ Any text... ]]></text>
<javascript><![CDATA[ function doSomething(){} ]]></javascript>
現在、上記の例は解析されます。私が 2 日間試みてきたことは、org.apache.xerces.impl.XMLScanner を試して拡張することです。これにより、次の例は上記と同じように解析されます。
例:
<text>Any text...</text>
<javascript>function doSomething(){}</javascript>
以下は私が現在持っているものです。scanCDATASection()
親実装からコピーされfEntityScanner.scanData("</javascript>", fStringBuffer)
、二重閉じ中括弧の代わりに終了タグを探すように行のみが変更されています。問題が何であるかを特定するのは難しいですがEntityScanner.scanData("</javascript>")
、「if」ステートメントに入らないため、正しく機能していないと思います。scanCDATASection()
または、内部への呼び出しを挿入しようとしている方法scanContent()
が問題を引き起こしています。このタスクを達成するためのよりクリーンで簡単なアプローチがあると想像する必要があります。私は XML パーサーをカスタマイズした経験がなく、アプリケーションで SAXParser を使用するたびにデフォルトのセットアップが使用されます。任意の提案/ヒントをいただければ幸いです。
public class JavaScriptScanner extends org.apache.xerces.impl.XMLNSDocumentScannerImpl
{
private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
public JavaScriptScanner()
{
super();
}
@Override
protected int scanContent() throws IOException, XNIException
{
if ("javascript".equals(fCurrentElement.rawname))
{
scanCDATASection();
setScannerState(SCANNER_STATE_CONTENT);
}
return super.scanContent();
}
protected boolean scanCDATASection() throws IOException, XNIException
{
// call handler
if (fDocumentHandler != null) {
fDocumentHandler.startCDATA(null);
}
while (true) {
fStringBuffer.clear();
if (!fEntityScanner.scanData("</javascript>", fStringBuffer) ||
fStringBuffer.toString().contains("</javascript")) {
if (fDocumentHandler != null && fStringBuffer.length > 0) {
fDocumentHandler.characters(fStringBuffer, null);
}
int brackets = 0;
while (fEntityScanner.skipChar(']')) {
brackets++;
}
if (fDocumentHandler != null && brackets > 0) {
fStringBuffer.clear();
if (brackets > XMLEntityManager.DEFAULT_BUFFER_SIZE) {
// Handle large sequences of ']'
int chunks = brackets / XMLEntityManager.DEFAULT_BUFFER_SIZE;
int remainder = brackets % XMLEntityManager.DEFAULT_BUFFER_SIZE;
for (int i = 0; i < XMLEntityManager.DEFAULT_BUFFER_SIZE; i++) {
fStringBuffer.append(']');
}
for (int i = 0; i < chunks; i++) {
fDocumentHandler.characters(fStringBuffer, null);
}
if (remainder != 0) {
fStringBuffer.length = remainder;
fDocumentHandler.characters(fStringBuffer, null);
}
}
else {
for (int i = 0; i < brackets; i++) {
fStringBuffer.append(']');
}
fDocumentHandler.characters(fStringBuffer, null);
}
}
if (fEntityScanner.skipChar('>')) {
break;
}
if (fDocumentHandler != null) {
fStringBuffer.clear();
fStringBuffer.append("]]");
fDocumentHandler.characters(fStringBuffer, null);
}
}
else {
if (fDocumentHandler != null) {
fDocumentHandler.characters(fStringBuffer, null);
}
int c = fEntityScanner.peekChar();
if (c != -1 && isInvalidLiteral(c)) {
if (XMLChar.isHighSurrogate(c)) {
fStringBuffer.clear();
scanSurrogates(fStringBuffer);
if (fDocumentHandler != null) {
fDocumentHandler.characters(fStringBuffer, null);
}
}
else {
reportFatalError("InvalidCharInCDSect",
new Object[]{Integer.toString(c,16)});
fEntityScanner.scanChar();
}
}
}
}
fMarkupDepth--;
// call handler
if (fDocumentHandler != null) {
fDocumentHandler.endCDATA(null);
}
return true;
}
}