【问题标题】:Parsing nested XML tags with possible duplicates using SAX Parser. Java使用 SAX 解析器解析可能重复的嵌套 XML 标记。爪哇
【发布时间】:2013-02-08 02:46:52
【问题描述】:

我的程序的概念是解析一个 XML 文件,该文件可以描述 XML 流中的一组类。每个类显然可以有几个方法和几个属性。反过来,这些方法也可以有多个参数。

以下是 XML 文件的示例:

<stream>
<class package="Mainpack" name="Person" visibility="public" alias="Aaron" type="class" spot="C">
    <property name="id" type="String" visibility="public"></property>
    <property name="name" type="String" visibility="public"></property>
    <method name="setID" return="void" visibility="public">
    <parameter name="name" type="string"> </parameter>
    </method>
    <method name="getID" return="String" visibility="public"></method>
</class>
</stream>

每个元素(流、类等)都有一个类,用 getter、setter 和一个空的构造函数来描述它。该流包含一个类列表。类包含名称、包等的属性...以及方法和参数的列表(它们本身是单独的类)。我不会包括这些,因为我认为它们很简单。

这是我写的 XMLHandler 类:

public class XMLHandler extends DefaultHandler {

Boolean currentElement = false;
String currentValue = null;

public static XMLStream xmlStream;

    public XMLClass xmlClass = null;
    public XMLMethod xmlMethod = null;
    public XMLProperty xmlProperty = null;
    public XMLParameter xmlParameter = null;

@Override
public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {
    currentElement = true;

    switch (localName) {
        case "stream":
            {
                xmlStream =  new XMLStream();
            }
        case "class":
            {
                /** Start and get attribute values */
                xmlClass = new XMLClass();
                String attr = attributes.getValue("package");
                xmlClass.setPackageName(attr);
                attr = attributes.getValue("name");
                xmlClass.setClassName(attr);
                attr = attributes.getValue("visibility");
                xmlClass.setVisibility(attr);
                attr = attributes.getValue("alias");
                xmlClass.setAlias(attr);
                attr = attributes.getValue("type");
                xmlClass.setType(attr);
                attr = attributes.getValue("spot");
                xmlClass.setSpot(attr.charAt(0));
                break;
            }
        case "method":
            {
                xmlMethod = new XMLMethod();
                String attr = attributes.getValue("name");
                xmlMethod.setName(attr);
                attr = attributes.getValue("return");
                xmlMethod.setReturnType(attr);
                attr = attributes.getValue("visibility");
                xmlMethod.setVisibility(attr);
                xmlClass.addMethod(xmlMethod);
                break;
            }
        case "property":
            {
                xmlProperty = new XMLProperty();
                String attr = attributes.getValue("name");
                xmlProperty.setName(attr);
                attr = attributes.getValue("type");
                xmlProperty.setType(attr);
                attr = attributes.getValue("visibility");
                xmlProperty.setVisibility(attr);
                xmlClass.addProperty(xmlProperty);
                break;
            }
        case "parameter":
            {
                xmlParameter = new XMLParameter();
                String attr = attributes.getValue("name");
                xmlParameter.setName(attr);
                attr = attributes.getValue("type");
                xmlParameter.setType(attr);
                xmlMethod.addParameter(xmlParameter);
                break;
            }
        }
}

/** Called when tag closing ( ex:- <name>AndroidPeople</name> 
 * -- </name> )*/
@Override
public void endElement(String uri, String localName, String qName)
        throws SAXException {

    currentElement = false;

            if (localName.equalsIgnoreCase("class"))
                xmlStream.addClass(xmlClass);
            else if (localName.equalsIgnoreCase("method"))
                xmlClass.addMethod(xmlMethod);
            else if (localName.equalsIgnoreCase("property"))
                xmlClass.addProperty(xmlProperty);
            else if (localName.equalsIgnoreCase("parameter"))
                xmlMethod.addParameter(xmlParameter);
}

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

    if (currentElement) {
        currentValue = new String(ch, start, length);
        currentElement = false;
    }

}

}

我希望逻辑是正确的。当解析器遇到流标签并设置属性时,它会创建一个 Stream 实例。当遇到一个类标签时,它也会这样做。在类的结束标记上,类实例被添加到流的类列表中。对于与类相关的方法和属性以及与方法相关的参数,此行为会重复。

我正在 Windows 应用程序中测试解析器,但您可以使用此方法:

public static void main(String[]args)
{
    try {

        String xmlst = "<stream>\n<class package=\"Mainpack\" name=\"Person\" "
                + "visibility=\"public\" alias=\"Aaron\" type=\"class\" spot=\"C\">\n   "
                + " <property name=\"id\" type=\"String\" visibility=\"public\"></property>\n  "
                + "  <method name=\"getID\" return=\"void\" visibility=\"public\">\n\t<parameter name=\"name\" type=\"string\">"
                + " </parameter>\n    </method>\n</class>\n</stream>";

        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        XMLHandler xh = new XMLHandler();

        InputSource is = new InputSource();
        is.setCharacterStream(new StringReader(xmlst));
        xr.setContentHandler(xh);
        xr.parse(new InputSource(is.getByteStream()));

        XMLStream xmlStream = XMLHandler.xmlStream;

        for (int i=0; i<xmlStream.getClasses().size(); i++)
        {
            System.out.println("*** CLASS ***");
            System.out.println(xmlStream.getClasses().get(i).getClassName());
            System.out.println(xmlStream.getClasses().get(i).getType());
            for (int j=0; j<xmlStream.getClasses().get(i).getProperties().size(); j++)
            {
                System.out.println("*** PROP ***");
                System.out.println(xmlStream.getClasses().get(i).getProperties().get(j).getName());
                System.out.println(xmlStream.getClasses().get(i).getProperties().get(j).getType());
            }
            for (int j=0; j<xmlStream.getClasses().get(i).getMethods().size(); j++)
            {
                System.out.println("*** METH ***");
                System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getName());
                System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getReturnType());
                for (int k=0; k<xmlStream.getClasses().get(i).getMethods().get(j).getParameters().size(); k++)
                {
                    System.out.println("*** PARAMS ***");
                    System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getParameters().get(k).getName());
                    System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getParameters().get(k).getType());
                }
            }

        }

    } catch (IOException ex) {
        Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ParserConfigurationException ex) {
        Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SAXException ex) {
        Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
    }
}

程序在运行以下行时遇到 MalformedURLException: "xr.parse(new inputSource(is.getByteStream()));"

有没有人知道什么是错的?

【问题讨论】:

    标签: java xml-parsing nested duplicates saxparser


    【解决方案1】:

    将您的 xml 文档保存为 .xml 文档(nuff 说)并尝试这种方法来运行您的解析器:

    XMLReader reader = XMLReaderFactory.createXMLReader();
    XMLHandler xh = new XMLHandler();
    reader.setContentHandler(xh);
    reader.parse(PATH_TO_FILE);
    

    代替你的代码:

    SAXParserFactory spf = SAXParserFactory.newInstance();
    SAXParser sp = spf.newSAXParser();
    XMLReader xr = sp.getXMLReader();
    XMLHandler xh = new XMLHandler();
    
    InputSource is = new InputSource();
    is.setCharacterStream(new StringReader(xmlst));
    xr.setContentHandler(xh);
    xr.parse(new InputSource(is.getByteStream()));
    

    希望对你有帮助。

    【讨论】:

    • 遇到了一个新错误,但它与 XMLHandler 有关。我会尝试修复它并回复您。
    • @user1028408,好的,我在线
    • 好的,我已经修复了程序,它运行良好。有一个小问题,我没有在对象的构造函数中初始化列表。但是,我仍然希望使用直接输入字符串来执行此操作,而不是从 XML 文件中解析。你知道怎么做吗?
    • @user1028408,不客气)不,我不知道,但我可以向您保证,保存 xml 文档的最佳位置是单独的文件 :)
    猜你喜欢
    • 1970-01-01
    • 2012-08-27
    • 2012-05-26
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 2011-06-17
    • 2011-08-13
    • 2013-01-08
    相关资源
    最近更新 更多