java - 在没有现有解析器实现的情况下用 Java 构建 XML 解析器

标签 java xml parsing dom

是否有一种在 Java 中创建原始 XML 解析器而不使用 Jackson、JDK 和 Document Builder 实现的好方法?理论上这应该是什么样子?

例如实现基本元素定义语法的解析:

<root>
<first></first>
<second></second>
</root>

实现解析元素树的 pretty-print :每个元素都在单独的 行,嵌套元素缩进 4 个空格,并通过 < 和 > 对 '<' 和 '>' 符号进行基本转义 解析:

<escaped&lt;&gt;></escaped&lt;&gt;>

然后,实现解析内联空元素:

<root>
<empty/>
</root>

最佳答案

我会使用基于已编译正则表达式的分词器构建一个递归下降解析器(虽然不可能使用正则表达式来解析 XML,但使用 XML 的正则表达式并没有什么问题)标记化)。

我将分词器界面设计大致如下(内部使用扫描仪):

class XmlTokenizer {
  String getCurrentText();
  boolean tryConsumeStartTagStart();
  boolean tryConsumeAttributeName();
  boolean tryConsumeText();
  ...

然后解析器可以尝试当前位置有效的标记类型,并使用 getCurrentText() 方法获取相应的文本(例如元素或属性名称)。

例如,内容解析如下所示:

void parseNodeContent(Node node) {
  while (true) {
    if (tokenizer.tryConsumeText()) {
      node.appendText(getCurrentText());
    } else if (tryConsumeStartTagStart()) {
      node.append(parseElement());
    } else if

      ...  // processing instructions, entity references

    } else {
      // Let the caller deal with all the rest, including errors.
      break;
    }
  }
}

元素解析可能如下所示:

// Precondition: on element start
// Postcondition: on element end
Element parseElement() {
  Element result = new Element(tokenizer.getCurrentText());
  while (tryConsumeAttributeName()) {
    String attributeName = tokenizer.getCurrentText();

    ... // attribute value parsing

  }
  if (!tokenizer.tryConsumeStartTagEndSelfClosing()) {
    if (!tokenizer.tryConsumeStartTagEnd()) {
      throw new RuntimeException("Invalid start tag end");
    }
    parseContent(result);
    if (!tokenizer.tryConsumeEndTag(result.name())) {
      throw new RuntimeException("End tag missing for " +result.name());
    }
  }
  return result;
}

我从 Kenton Varla 的 Protocol Buffer 定义解析器中选择了 tryConsumeXxx() 样式,我发现它非常有用。

关于java - 在没有现有解析器实现的情况下用 Java 构建 XML 解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46744236/

相关文章:

java - 当其中一个属性是枚举且两个类具有不同支持值时,Orika 映射器

java - 如何更改按钮背景的颜色

java - 如何解析txt文件中的2列int

c - 用于从头文件中提取和操作 C 函数的搜索工具

java - Joda Time - 将 UTC 日期时间转换为日期 - 使用 Joda 版本 1.2.1.1

java - Apache commons 文件上传替代方案

sql-server - 在 SQL Select 语句中读取 XML 值

python - 使用Python获取html文件上所有<a>标签中href属性的值

java - 制作一个空心钻石,里面有一个单词

php - 没有 Moodle 的示例(演示)数据?