【问题标题】:Can't read some attributes with SAX无法使用 SAX 读取某些属性
【发布时间】:2011-01-04 14:25:09
【问题描述】:

我正在尝试使用 SAX 解析该文档:

<scxml version="1.0" initialstate="start" name="calc"> 
  <datamodel> 
      <data id="expr" expr="0" /> 
      <data id="res" expr="0" /> 
  </datamodel> 
  <state id="start"> 
      <transition event="OPER" target="opEntered" /> 
      <transition event="DIGIT" target="operand" /> 
  </state> 
  <state id="operand"> 
      <transition event="OPER" target="opEntered" /> 
      <transition event="DIGIT" /> 
  </state> 
</scxml>

除了“initialstate”和“name”之外的所有属性我都读得很清楚... 我使用 startElement 处理程序获取属性,但 scxml 的属性列表的大小为零。为什么?我该如何克服这个问题?

编辑

public void startElement(String uri, String localName, String qName, Attributes attributes){
  System.out.println(attributes.getValue("initialstate"));
  System.out.println(attributes.getValue("name")); 
}

在解析第一个标签时,它不起作用(打印“null”两次)。事实上,

attributes.getLength();

计算为零。

谢谢

【问题讨论】:

  • 我想一些代码会很受欢迎。
  • public void startElement(String uri, String localName, String qName, Attributes attributes) { System.out.println(attributes.getValue("initialstate")); System.out.println(attributes.getValue("name"));解析第一个标签时,这不起作用。
  • 文档中是否有 XML 命名空间?
  • 这是取自 scxml 标准的规范示例,所以...不,没有 xml 命名空间。它们与我的问题相关吗?

标签: java sax xml-parsing


【解决方案1】:

我有一个来自 there 的完整示例,并针对您的文件进行了调整:

public class SaxParserMain {

    /**
     * @param args
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     */
    public static void main(String[] args) throws ParserConfigurationException, SAXException,
            IOException {
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        CustomHandler handler = new CustomHandler();
        parser.parse(new File("file/scxml.xml"), handler);
    }
}

public class CustomHandler extends DefaultHandler {

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes)
            throws SAXException {
        System.out.println();
        System.out.print("<" + qName + "");
        if (attributes.getLength() == 0) {
            System.out.print(">");
        } else {
            System.out.print(" ");
            for (int index = 0; index < attributes.getLength(); index++) {
                System.out.print(attributes.getLocalName(index) + " => "
                        + attributes.getValue(index));
            }
            System.out.print(">");
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        System.out.print("\n</" + qName + ">");
    }
}

输出是:

<scxml version => 1.0initialstate => startname => calc>
<datamodel>
<data id => exprexpr => 0>
</data>
<data id => resexpr => 0>
</data>
</datamodel>
<state id => start>
<transition event => OPERtarget => opEntered>
</transition>
<transition event => DIGITtarget => operand>
</transition>
</state>
<state id => operand>
<transition event => OPERtarget => opEntered>
</transition>
<transition event => DIGIT>
</transition>
</state>
</scxml>

【讨论】:

  • 嗯,谢谢,问题解决了。问题是 sax 总是使用相同的属性实例,每次引发事件时都会填充它。我假设它总是一个/不同的/实例。叹! :)
  • 是的,javadoc说:“atts - 附加到元素的属性。如果没有属性,它应该是一个空的Attributes对象。这个对象在startElement返回后的值未定义"
【解决方案2】:

Attributes.getValue() 并不像看起来那么简单。 javadoc 说:

通过 XML 查找属性的值 限定(前缀)名称。

因此,如果存在任何命名空间复杂性,仅传递“initialstate”可能不起作用,因为“initialstate”在技术上不是限定名称。

我建议尝试一下Attributes 类中的其他方法,例如getValue(int),您可能会获得更多成功。


edit:另一种可能性是startElement 的调用不是指您认为的元素。您是否验证了localName 参数确实是scxml,而不是别的?

【讨论】:

  • 问题是属性列表的长度对于第一个标签是零...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 2019-12-18
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多