如何用Java解析高级XML文件

时间:2010-11-23 20:38:33

标签: java xml collada

我见过很多关于如何用Java读取XML文件的例子。但它们只显示简单的XML文件。例如,它们展示了如何从XML文件中提取名字和姓氏。但是,我需要从collada XML文件中提取数据。像这样:

<library_visual_scenes>
    <visual_scene id="ID1">
        <node name="SketchUp">
            <instance_geometry url="#ID2">
                <bind_material>
                    <technique_common>
                        <instance_material symbol="Material2" target="#ID3">
                            <bind_vertex_input semantic="UVSET0" input_semantic="TEXCOORD" input_set="0" />
                        </instance_material>
                    </technique_common>
                </bind_material>
            </instance_geometry>
        </node>
    </visual_scene>
</library_visual_scenes>

这只是collada文件的一小部分。在这里,我需要提取visual_scene的id,然后提取instance_geometry的url并持续instance_material的目标。当然我需要提取更多,但我不明白如何使用它,这是一个开始的地方。

到目前为止我有这个代码:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
    builder = factory.newDocumentBuilder();
}
catch( ParserConfigurationException error ) {
    Log.e( "Collada", error.getMessage() ); return;
}
Document document = null;
try {
    document = builder.parse( string );
}
catch( IOException error ) {
    Log.e( "Collada", error.getMessage() ); return;
}
catch( SAXException error ) {
    Log.e( "Collada", error.getMessage() ); return;
}
NodeList library_visual_scenes = document.getElementsByTagName( "library_visual_scenes" );

似乎网络上的大多数示例与此类似:http://www.easywayserver.com/blog/java-how-to-read-xml-file/

当我想要提取更深层的标签或找到一个阅读/解析XML文件的好教程时,我需要帮助弄清楚要做什么。

4 个答案:

答案 0 :(得分:6)

实际上,当您致电builder.parse(string)时,您的解析本身已经完成。您现在需要知道的是如何从解析的XML文档中选择/查询信息。

我同意@khachik关于如何做到这一点。详细说明(因为没有其他人发布答案):

XPath是提取信息的最便捷方式,如果您的输入文档不是很大,XPath就足够快了。 Here是Java中XPath的一个很好的入门教程。如果您需要随机访问XML数据,也建议使用XPath(即,如果您必须以与源文档中显示的顺序不同的顺序来回提取树中的数据),因为SAX是为线性访问而设计的。 / p>

一些示例XPath表达式:

  • 提取visual_scene的id:/*/visual_scene/@id
  • instance_geometry的网址:/*/visual_scene/node/instance_geometry/@url
  • 名称为Sketchup的节点的instance_geometry的url:/*/visual_scene/node[@name = 'Sketchup']/instance_geometry/@url
  • instance_material的目标:/*/visual_scene/node/instance_geometry/bind_material/technique_common/instance_material/@target

由于COLLADA模型可能非常大,您可能需要执行基于SAX的过滤器,这样您就可以在流模式下处理文档,而无需立即将其全部保存在内存中。但是,如果现有的解析XML代码已经运行良好,那么您可能不需要SAX。 SAX比XPath更难以提取特定数据。

答案 1 :(得分:4)

您在代码中使用DOM DOM创建了它解析的xml文件的树结构,您必须遍历树以获取各个节点中的信息。
在您的代码中,您所做的就是创建树表示。即

document = builder.parse( string );//document is loaded in memory as tree  

现在您应该参考DOM apis以了解如何获取所需的信息。

NodeList library_visual_scenes = document.getElementsByTagName( "library_visual_scenes" );

例如,此方法返回具有指定名称的所有元素的NodeList 现在你应该遍历NodeList

 for (int i = 0; i < library_visual_scenes.getLength(); i++) {
   Element element = (Element) nodes.item(i);
   Node visual_scene = element.getFirstChild();
   if(visual_scene.getNodeType() == Node.ELEMENT_NODE)
   {
      String id = ((Element)visual_scene).getAttribute(id);
      System.out.println("id="+id);
    }
 }

免责声明:这是一个示例代码。没有编译它。它向您展示了这个概念。你应该研究一下DOM apis。

答案 2 :(得分:1)

EclipseLink JAXB (MOXy)有一个有用的@XmlPath扩展,用于利用XPath填充对象。这可能就是你要找的东西。注意:我是MOXy技术主管。

以下示例将简单地址对象映射到Google的地理编码信息表示:

package blog.geocode;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="kml")
@XmlType(propOrder={"country", "state", "city", "street", "postalCode"})
public class Address {

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:Thoroughfare/ns:ThoroughfareName/text()")
    private String street;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:LocalityName/text()")
    private String city;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:AdministrativeAreaName/text()")
    private String state;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryNameCode/text()")
    private String country;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:PostalCode/ns:PostalCodeNumber/text()")
    private String postalCode;

}

对于示例的其余部分,请参阅:

答案 3 :(得分:0)

如今,几个java RAD工具都有来自给定DTD的java代码生成器,因此您可以使用它们。