如何从 XMLReader 获取属性

2024-04-06

我有一些 HTML 正在转换为Spanned using Html.fromHtml(...),并且我在其中使用了一个自定义标签:

<customtag id="1234">

所以我实现了一个TagHandler处理这个自定义标签,如下所示:

public void handleTag( boolean opening, String tag, Editable output, XMLReader xmlReader ) {

    if ( tag.equalsIgnoreCase( "customtag" ) ) {

        String id = xmlReader.getProperty( "id" ).toString();
    }
}

在这种情况下,我得到一个 SAX 异常,因为我相信“id”字段实际上是一个属性,而不是属性。然而,没有一个getAttribute()方法用于XMLReader。所以我的问题是,如何使用它获取“id”字段的值XMLReader?谢谢。


可以使用XmlReader由...提供TagHandler并无需反射即可访问标签属性值,但该方法比反射更不简单。诀窍是替换ContentHandler被使用过XmlReader与自定义对象。更换ContentHandler只能在调用中完成handleTag()。这就提出了获取第一个标签的属性值的问题,可以通过在 html 开头添加自定义标签来解决这个问题。

import android.text.Editable;
import android.text.Html;
import android.text.Spanned;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import java.util.ArrayDeque;

public class HtmlParser implements Html.TagHandler, ContentHandler
{
    public interface TagHandler
    {
        boolean handleTag(boolean opening, String tag, Editable output, Attributes attributes);
    }

    public static Spanned buildSpannedText(String html, TagHandler handler)
    {
        // add a tag at the start that is not handled by default,
        // allowing custom tag handler to replace xmlReader contentHandler
        return Html.fromHtml("<inject/>" + html, null, new HtmlParser(handler));
    }

    public static String getValue(Attributes attributes, String name)
    {
        for (int i = 0, n = attributes.getLength(); i < n; i++)
        {
            if (name.equals(attributes.getLocalName(i)))
                return attributes.getValue(i);
        }
        return null;
    }

    private final TagHandler handler;
    private ContentHandler wrapped;
    private Editable text;
    private ArrayDeque<Boolean> tagStatus = new ArrayDeque<>();

    private HtmlParser(TagHandler handler)
    {
        this.handler = handler;
    }

    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader)
    {
        if (wrapped == null)
        {
            // record result object
            text = output;

            // record current content handler
            wrapped = xmlReader.getContentHandler();

            // replace content handler with our own that forwards to calls to original when needed
            xmlReader.setContentHandler(this);

            // handle endElement() callback for <inject/> tag
            tagStatus.addLast(Boolean.FALSE);
        }
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes)
            throws SAXException
    {
        boolean isHandled = handler.handleTag(true, localName, text, attributes);
        tagStatus.addLast(isHandled);
        if (!isHandled)
            wrapped.startElement(uri, localName, qName, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException
    {
        if (!tagStatus.removeLast())
            wrapped.endElement(uri, localName, qName);
        handler.handleTag(false, localName, text, null);
    }

    @Override
    public void setDocumentLocator(Locator locator)
    {
        wrapped.setDocumentLocator(locator);
    }

    @Override
    public void startDocument() throws SAXException
    {
        wrapped.startDocument();
    }

    @Override
    public void endDocument() throws SAXException
    {
        wrapped.endDocument();
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException
    {
        wrapped.startPrefixMapping(prefix, uri);
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException
    {
        wrapped.endPrefixMapping(prefix);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException
    {
        wrapped.characters(ch, start, length);
    }

    @Override
    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
    {
        wrapped.ignorableWhitespace(ch, start, length);
    }

    @Override
    public void processingInstruction(String target, String data) throws SAXException
    {
        wrapped.processingInstruction(target, data);
    }

    @Override
    public void skippedEntity(String name) throws SAXException
    {
        wrapped.skippedEntity(name);
    }
}

使用此类读取属性很容易:

    HtmlParser.buildSpannedText("<x id=1 value=a>test<x id=2 value=b>", new HtmlParser.TagHandler()
    {
        @Override
        public boolean handleTag(boolean opening, String tag, Editable output, Attributes attributes)
        {
            if (opening && tag.equals("x"))
            {
                String id = HtmlParser.getValue(attributes, "id");
                String value = HtmlParser.getValue(attributes, "value");
            }
            return false;
        }
    });

这种方法的优点是它允许禁用某些标签的处理,同时对其他标签使用默认处理,例如你可以确保ImageSpan未创建对象:

    Spanned result = HtmlParser.buildSpannedText("<b><img src=nothing>test</b><img src=zilch>",
            new HtmlParser.TagHandler()
            {
                @Override
                public boolean handleTag(boolean opening, String tag, Editable output, Attributes attributes)
                {
                    // return true here to indicate that this tag was handled and
                    // should not be processed further
                    return tag.equals("img");
                }
            });
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 XMLReader 获取属性 的相关文章

随机推荐

  • 获取数组长度?

    我试图获取数组的长度 但我不断收到此错误 所需对象 难道我做错了什么 Dim columns As Variant columns Array A ID D Name Debug Print columns Length Error Obj
  • 如何找到具有负值的索引并将该值替换为最接近的正值索引值?

    我知道如何从矩阵中查找具有负值的索引 matrix matrix lt 0 something should be done 但不知道如何用最接近的恰好为正的索引值替换它们的值 这里最近的索引应该与观察到的索引位于同一行 如果该行中没有具有
  • 是否可以仅使用 T-SQL 命令而不是 SSIS 让 SQL Server 登录 SFTP 并上传文件?

    我有一个 SSIS 包 它可以登录到我客户端的 SFTP 站点并使用发送到 WinSCP 的命令上传文件 这个包经常失败并且很难使用 Visual Studio 崩溃如此频繁 以至于我的团队拒绝再使用它 我们正在将所有自动化任务迁移到存储过
  • 使用 R 列出 xlsx 工作表名称

    是否可以在 xlsx 文件中生成工作表名称列表 或者 也许我可以检查工作表名称是否存在 如果不存在 则继续执行某些指定的功能 With xlsx库中 您可以使用 getSheets 获取现有工作簿中的工作表列表 wb lt loadWork
  • 在JSF和JPA项目中使用POJO作为模型,是吗?

    我正在使用 JSF 2 和 JPA 2 EclipseLink 2 3 开发一个项目 在 JSF 2 中 我了解到我们必须将模型与控制器分开 并将同样的东西与视图分开 感谢 BalusC 但现在有了从 JPA 生成的 POJO 我想知道 b
  • 为什么跨域 angularjs $http.post 请求在 XMLHttpRequest 成功时失败?

    我正在尝试使用 Angular 版本 1 0 5 Web 应用程序中的应用程序密钥和令牌来练习 Trello API 服务器似乎已正确配置来处理CORS http en wikipedia org wiki Cross origin res
  • JavaFX WebView 不加载 jar 中的上层文件夹脚本

    我正在尝试创建基于 JavaFX WebView 的代码编辑器 我将 jquery 加载到由 WebView 加载的 html 文件中 如下所示
  • 在 git 中,如何将我的标签与远程服务器同步?

    有没有办法让我的本地 git 标签与远程标签保持同步 也就是说 不仅在创建时获得新标签 像往常一样 当fetch ing pull ing 而且还可以删除遥控器上不再存在的标签 并在其他人使用时删除现有标签git push f是一个标签 我
  • 实体框架和 WCF(返回附加到上下文的实体)

    我有一个 WCF 服务 它在我的 Repository 对象之一中调用以下方法 以在数据库中创建一个新的销售对象 public static Sale New Sale sale using var ctx new DBcontext ct
  • 如何更改 Minikube 中 api-server 的身份验证机制?

    我有一个本地 minikube 安装 我想更改 api server 的身份验证机制并重新启动并测试它 我读过的所有文档都缺少此信息 是的你可以 kubernetes API 服务器 控制器管理器和调度程序都作为 minikube 中的静态
  • 有没有办法对 unsigned long long A 和 B 执行 (A*B) mod M 而不会溢出?

    我不想经历在 Windows 上安装 GMP 的噩梦 我有两个数字A和B unsigned long longs 最多 10 10 左右的数量级 但即使在这样做时 A M B M M 我得到整数溢出 是否有用于计算的自制函数 A B M对于
  • 特定于操作系统的 CSS?

    过去 我发现不同平台上相同浏览器中的 CSS 几乎没有区别 Mac 上 Safari 上的页面通常与 Windows 上的 Safari 看起来相同 FF Win 与 FF Mac 也是如此 然而 现在我遇到了一个问题 与 PC 浏览器相比
  • 为什么重复捕获组会返回这些字符串?

    有人可以解释为什么以下返回 cc 吗 gt gt gt re match aabbcc group 1 cc 有人告诉我 因为它将每场比赛放入组 1 所以最后一场比赛是 cc 真的吗 那么下面怎么解释呢 gt gt gt re match
  • .net 程序集清单中是否提升了依赖项?

    我使用 VS2010 构建了一个程序集 它具有对 NET 4 0 的普通引用 它还引用了 Ionic Zip 后者引用了 NET 2 0 当我使用 ildasm 查看清单时 我发现 NET 的两个版本都是我的程序集的直接依赖项 并且在 Io
  • Azure 服务总线消息队列用户错误指标

    我正在帮助调查和诊断我们遇到的一些问题 并注意到服务总线队列上的用户错误指标正在发生变化 我想确切地知道这个指标的含义 如文档所示https learn microsoft com en us azure service bus messa
  • 如何通过网页将参数传递到 PHP 脚本中?

    每当网页加载时我都会调用 PHP 脚本 但是 PHP 脚本需要运行一个参数 我在测试脚本时通常通过命令行传递该参数 每次加载页面时运行脚本时如何传递此参数 假设您在命令行上传递参数 如下所示 php path to wwwpublic pa
  • SQL Server分页查询

    呃呃呃 我已经为此苦苦挣扎了很长时间 我可以用 MySQL 轻松做到这一点 但用 SQL Server 就不行 这是应该连接在一起的简化表格 通过使用内连接语法将所有这些组合起来 我必须编写一个查询以用于将来的分页 顺便说一句 PHP 假设
  • 从字典和数组的 plist 中读取/写入数据,并将不同级别加载到 TableView 中

    我对使用属性列表有点困惑 我已经阅读了有关该主题的大多数其他问题 但我仍然很困惑 因为它们只进入一层 因此任何帮助将不胜感激 我想加载一个存储数据的plist 如下所示 我的故事板中有三个视图控制器 两个 TableView 控制器和一个空
  • Android获取当前歌曲播放和歌曲更改事件,例如Musixmatch

    我想要实现的目标非常相似是在做 我需要在音乐开始播放以及歌曲更改时得到通知 所有这些都在服务中 因为我的应用程序可能会关闭 甚至 musicmatch 也会这样做 在上述情况下 即使 Musixmatch 应用程序未运行 当我在 Spoti
  • 如何从 XMLReader 获取属性

    我有一些 HTML 正在转换为Spanned using Html fromHtml 并且我在其中使用了一个自定义标签