sphinx4 XML配置文件解析

回顾一下,要得到一个对象,首先是创建ConfigurationManager,同时在构造方法中传入一个xml文件的路径,然后调用ConfigurationManager的lookup方法。那么sphinx4内部是如何解析xml文件的呢?


首先我们看下 ConfigurationManager 带有一个String类型的构造函数


// 构造函数,传入一个xml配置文件的名称,内部自行转为URL格式

public ConfigurationManager(String configFileName) throws PropertyException {

       this(ConfigurationManagerUtils.getURL(new File(configFileName)));

}


这个函数比较简单,它把传进来的配置文件名称转为一个URL,然后调用了另一个构造函数


public ConfigurationManager(URL url) throws PropertyException {


       configURL = url;


       try {

                   rawPropertyMap = new SaxLoader(url, globalProperties).load();

         } catch (IOException e) {

                   throw new RuntimeException(e);

         }

         // 此处省略部分代码

         ..................

}


这里new了一个SaxLoader对象,然后把之前的url传递给它,同时还传了一个globalProperties。然后调用SaxLoader的load方法,并将返回的结果保存在rawPropertyMap中。从这里我们可以看出,sphinx4采用的是SAX解析技术。


SAX是基于事件驱动的一种解析方式,每解析到一个节点就会触发一个事件,详细的大家可以上网查找相关资料。


下面我们再看一下load方法:


public Map<String, RawPropertyData> load() throws IOException {

               try {

                           SAXParserFactory factory = SAXParserFactory.newInstance();

                           XMLReader xr = factory.newSAXParser().getXMLReader();

                           ConfigHandler handler = new ConfigHandler(rpdMap, globalProperties,             replaceDuplicates, url);

                           xr.setContentHandler(handler);

                           xr.setErrorHandler(handler);

                           InputStream is = url.openStream();

                           xr.parse(new InputSource(is));

                           is.close();

                       } catch (SAXParseException e) {

                               String msg = "Error while parsing line " + e.getLineNumber() + " of " + url + ": " + e.getMessage();

                               throw new IOException(msg);

                       } catch (SAXException e) {

                               throw new IOException("Problem with XML: " + e);

                       } catch (ParserConfigurationException e) {

                               throw new IOException(e.getMessage());

                       }


   return rpdMap;

}


这个是SAX解析的标准流程,首先得到一个SAXParserFactory实例,然后获取到XMLReader,接下去比较重要的就是创建和设置ConfigHandler对象,所有的解析操作都是在这个对象中完成的。



下面重点分析一下ConfigHandler的具体解析过程:


元素解析开始时,

如果遇到component节点,根据它的name和type值new一个RawPropertyData:


       String curComponent = attributes.getValue("name");

       String curType = attributes.getValue("type");

       rpd = new RawPropertyData(curComponent, curType);


如果遇到property节点,把解析到的name和value值添加到RawPropertyData这个对象的

private Map<String, Object> properties中,即相当于是这个component拥有的所有属性:


       String name = attributes.getValue("name");

       String value = attributes.getValue("value");


       // 添加到RawPropertyData的Map中

       rpd.add(name, value);


元素解析结束时,

将本次解析创建的RawPropertyData添加到Map<String, RawPropertyData> rpdMap中:

if (qName.equals("component")) {

       rpdMap.put(rpd.getName(), rpd);

       rpd = null;

}


总结:配置文件中的每个<component>是通过RawPropertyData这个类来描述的,当整个xml文件解析完成后,rpdMap保存了所有component的信息,而每个component的属性值保在RawPropertyData这个类的成员变量Map<String, Object> properties中。



你可能感兴趣的:(java,语音识别,sphinx4)