对于 JEditorPane 结合 HTMLEditorKit 进行 HTML 解析时遇到的 Boolean/布尔处理问题,我来帮你分析可能的场景和解决方案。

常见场景与解决方案
HTML 属性解析为 Boolean
当解析 HTML 中的布尔属性(如 checked、disabled、readonly)时:
import javax.swing.text.html.*;
import javax.swing.text.*;
import javax.swing.*;
public class BooleanHtmlParser {
public static void main(String[] args) {
JEditorPane editorPane = new JEditorPane();
editorPane.setContentType("text/html");
// 解析带布尔属性的 HTML
String html = "<html><body>" +
"<input type='checkbox' checked>" +
"<input type='text' disabled>" +
"</body></html>";
editorPane.setText(html);
// 获取 HTML 文档并解析属性
HTMLDocument doc = (HTMLDocument) editorPane.getDocument();
Element root = doc.getDefaultRootElement();
// 遍历元素
traverseElements(root);
}
private static void traverseElements(Element element) {
AttributeSet attrs = element.getAttributes();
// 检查布尔属性
Object checkedAttr = attrs.getAttribute(HTML.Attribute.CHECKED);
Object disabledAttr = attrs.getAttribute(HTML.Attribute.DISABLED);
// 布尔属性处理
if (checkedAttr != null) {
System.out.println("Found checked attribute: " + checkedAttr);
// HTMLEditorKit 中布尔属性值可能是 null 或字符串
boolean isChecked = (checkedAttr == null ||
"true".equals(checkedAttr.toString()) ||
checkedAttr.equals(Boolean.TRUE));
}
// 递归处理子元素
for (int i = 0; i < element.getElementCount(); i++) {
traverseElements(element.getElement(i));
}
}
}
自定义 Boolean 解析器
创建自定义的 TagParser 来处理布尔属性:
import javax.swing.text.html.parser.*;
import java.util.*;
public class CustomBooleanParser extends DocumentParser {
public static class BooleanAwareParser extends HTMLEditorKit.ParserCallback {
private Map<String, Boolean> booleanAttributes = new HashMap<>();
@Override
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
// 处理布尔属性
for (HTML.Attribute attr : getBooleanAttributes()) {
Object value = a.getAttribute(attr);
if (value != null) {
boolean isBoolean = value.equals(Boolean.TRUE) ||
value.equals("") ||
value.equals(attr.toString());
if (isBoolean) {
booleanAttributes.put(attr.toString(), true);
// 转换为标准的 true/false
a.addAttribute(attr, Boolean.TRUE);
}
}
}
}
private List<HTML.Attribute> getBooleanAttributes() {
return Arrays.asList(
HTML.Attribute.CHECKED,
HTML.Attribute.DISABLED,
HTML.Attribute.READONLY,
HTML.Attribute.SELECTED,
HTML.Attribute.NOSHADE,
HTML.Attribute.NOWRAP,
HTML.Attribute.ISMAP
);
}
public Map<String, Boolean> getBooleanAttributesMap() {
return booleanAttributes;
}
}
public static void main(String[] args) {
String html = "<html><body>" +
"<input type='checkbox' checked>" +
"<input type='text' disabled readonly>" +
"<select><option selected>Option 1</option></select>" +
"</body></html>";
// 使用自定义解析器
HTMLEditorKit kit = new HTMLEditorKit();
JEditorPane editor = new JEditorPane();
editor.setEditorKit(kit);
BooleanAwareParser parser = new BooleanAwareParser();
try {
// 手动解析 HTML
javax.swing.text.html.parser.ParserDelegator delegator =
new javax.swing.text.html.parser.ParserDelegator();
delegator.parse(new java.io.StringReader(html), parser, true);
// 获取解析结果
Map<String, Boolean> booleanAttrs = parser.getBooleanAttributesMap();
System.out.println("Boolean attributes found: " + booleanAttrs);
} catch (Exception e) {
e.printStackTrace();
}
}
}
处理 Boolean 值的实用工具类
import javax.swing.text.html.*;
import javax.swing.text.*;
public class BooleanAttributeUtils {
/**
* 安全获取布尔属性值
*/
public static boolean getBooleanAttribute(AttributeSet attrs, HTML.Attribute attr) {
Object value = attrs.getAttribute(attr);
// 处理各种可能的 Boolean 表示形式
if (value == null) {
return false;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
// 处理字符串表示
String strVal = value.toString();
return "true".equalsIgnoreCase(strVal) ||
"checked".equalsIgnoreCase(strVal) ||
"selected".equalsIgnoreCase(strVal) ||
"disabled".equalsIgnoreCase(strVal) ||
"readonly".equalsIgnoreCase(strVal);
}
/**
* 在 HTML 文档中查找特定布尔属性
*/
public static List<Element> findElementsWithBooleanAttribute(
HTMLDocument doc, HTML.Attribute attr) {
List<Element> result = new ArrayList<>();
Element root = doc.getDefaultRootElement();
findElementsRecursive(root, attr, result);
return result;
}
private static void findElementsRecursive(
Element element, HTML.Attribute attr, List<Element> result) {
AttributeSet attrs = element.getAttributes();
if (attrs.getAttribute(attr) != null) {
result.add(element);
}
for (int i = 0; i < element.getElementCount(); i++) {
findElementsRecursive(element.getElement(i), attr, result);
}
}
/**
* 示例:使用工具类
*/
public static void main(String[] args) {
JEditorPane editor = new JEditorPane();
editor.setContentType("text/html");
editor.setText("<html><body>" +
"<input type='checkbox' id='c1' checked>" +
"<input type='radio' id='r1' checked>" +
"</body></html>");
HTMLDocument doc = (HTMLDocument) editor.getDocument();
// 查找所有包含 checked 属性的元素
List<Element> checkedElements =
findElementsWithBooleanAttribute(doc, HTML.Attribute.CHECKED);
for (Element elem : checkedElements) {
boolean isChecked = getBooleanAttribute(
elem.getAttributes(), HTML.Attribute.CHECKED);
System.out.println("Element: " + elem.getName() +
" checked: " + isChecked);
}
}
}
自定义 HTMLEditorKit 扩展
import javax.swing.text.html.*;
import javax.swing.text.*;
public class EnhancedHTMLEditorKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = new HTMLDocument() {
@Override
public HTMLEditorKit.ParserCallback getReader(int pos) {
return new HTMLDocument.HTMLReader(pos) {
@Override
public void handleSimpleTag(HTML.Tag t,
MutableAttributeSet a, int pos) {
// 处理自闭合标签的布尔属性
processBooleanAttributes(t, a);
super.handleSimpleTag(t, a, pos);
}
@Override
public void handleStartTag(HTML.Tag t,
MutableAttributeSet a, int pos) {
// 处理开始标签的布尔属性
processBooleanAttributes(t, a);
super.handleStartTag(t, a, pos);
}
private void processBooleanAttributes(HTML.Tag t,
MutableAttributeSet a) {
// 枚举所有属性
Enumeration<?> names = a.getAttributeNames();
while (names.hasMoreElements()) {
Object name = names.nextElement();
if (name instanceof HTML.Attribute) {
HTML.Attribute attr = (HTML.Attribute) name;
Object value = a.getAttribute(attr);
// 转换布尔值
if (value != null && !(value instanceof Boolean)) {
String strVal = value.toString();
if ("".equals(strVal) ||
attr.toString().equals(strVal)) {
a.addAttribute(attr, Boolean.TRUE);
}
}
}
}
}
};
}
};
return doc;
}
}
使用示例
public class Main {
public static void main(String[] args) {
// 使用增强的 EditorKit
JEditorPane editor = new JEditorPane();
editor.setEditorKit(new EnhancedHTMLEditorKit());
// 解析带布尔属性的 HTML
String html = "<html><body>" +
"<form>" +
"<input type='checkbox' checked='checked'> Checked" +
"<input type='checkbox'> Unchecked" +
"<input type='text' disabled='disabled'>" +
"<select><option selected='selected'>Selected</option></select>" +
"</form></body></html>";
editor.setText(html);
// 验证解析结果
HTMLDocument doc = (HTMLDocument) editor.getDocument();
// 使用工具类获取属性
boolean checkBox1Checked = BooleanAttributeUtils.getBooleanAttribute(
getFirstInputElement(doc), HTML.Attribute.CHECKED);
System.out.println("Checkbox checked: " + checkBox1Checked);
}
private static AttributeSet getFirstInputElement(HTMLDocument doc) {
Element root = doc.getDefaultRootElement();
return findElementByTag(root, HTML.Tag.INPUT);
}
private static AttributeSet findElementByTag(Element element, HTML.Tag tag) {
AttributeSet attrs = element.getAttributes();
Object name = attrs.getAttribute(
javax.swing.text.StyleConstants.NameAttribute);
if (tag.equals(name)) {
return attrs;
}
for (int i = 0; i < element.getElementCount(); i++) {
AttributeSet found = findElementByTag(element.getElement(i), tag);
if (found != null) return found;
}
return null;
}
}
- Swing 的 HTMLEditorKit 对布尔属性支持有限,需要手动处理
- 布尔属性值可能是:
null、String、Boolean对象 - 建议创建工具类统一处理布尔属性的转换和验证
- 自定义 Parser 可以提供更精确的控制
- 总是进行 null 检查,因为解析器可能返回 null
这些代码示例应该能帮你处理 JEditorPane 中的布尔属性解析问题,如果你有具体的错误信息或使用场景,请补充说明,我可以提供更精确的解决方案。