我正在使用 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>
目前上面的例子将被解析。我这两天一直在尝试做的是尝试扩展 org.apache.xerces.impl.XMLScanner,以便以下示例解析与上面相同。
例子:
<text>Any text...</text>
<javascript>function doSomething(){}</javascript>
以下是我目前拥有的。scanCDATASection()
是从父实现复制的,仅fEntityScanner.scanData("</javascript>", fStringBuffer)
更改了行以查找我的结束标记而不是双右括号。我很难确定问题出在哪里,但我认为EntityScanner.scanData("</javascript>")
它无法正常工作,因为我从未进入“if”语句。或者我要向scanCDATASection()
inside 注入调用的方式scanContent()
会导致问题。我不得不想象有一种更清洁、更直接的方法来完成这项任务。我没有定制 XML Parser 的经验,并且在我们的应用程序中每次使用 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;
}
}