使用xml解析来获取Java中的子标记值

时间:2015-04-20 11:09:30

标签: java xml parsing java-ee xml-parsing

我想解析动态生成的xml,它没有xml文件的任何预定义结构。我的Xml看起来像,

    <?xml version="1.0" encoding="UTF-8"?>
    <metadata>
    <control for="9bd2f8fd2421eb0b0a410feaa1f482c50551486a" name="first-name" type="input" datatype="string">
                    <resources lang="en">
                            <label>First Name</label>
                            <help />
                            <hint>Your first or given name
                            </hint>
                            <alert />
                    </resources>
                    <resources lang="fr">
                            <label>Prénom</label>
                            <help />
                            <hint>
                                    Votre prénom
                            </hint>
                                    <alert />
                    </resources>
                    <value>Rahul</value>
            </control>

<control for="9bd2f8fd2421eb0b0a410feaa1f482c50551486b" name="last-name" type="input" datatype="string">
                    <resources lang="en">
                            <label>Last Name</label>
                            <help />
                            <hint>Your last name
                            </hint>
                            <alert />
                    </resources>
                    <resources lang="fr">
                            <label>Prénom</label>
                            <help />
                            <hint>
                                    Votre prénom
                            </hint>
                                    <alert />
                    </resources>
                    <value>Sharma</value>
            </control>
    </metadata>

从上面的xml我需要获得以下细节,控制器标签中的Name属性以及标签和值标签的内容。所以我尝试了如下,

FileInputStream fis = new FileInputStream("test.xml");
        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fis);
        Node objects = doc.getDocumentElement();
        for (Node object = objects.getFirstChild(); object != null; object = object.getNextSibling()) {
            if (object instanceof Element) {
                Element e = (Element)object;
                System.out.println(e.getTagName());
                if (e.getTagName().equalsIgnoreCase("control")) {
                    String name = e.getAttribute("name");
                    System.out.println("It's a " + name + " control!");
                } 
               else {
                  System.out.println("I don't know what a " + e.getTagName() + " is for.");
                }
            }
        }

使用上面的代码,我可以在controller标签中获取name属性。现在我如何获得标签和价值标签的内容。

我需要以下输出,

name: first-name
label: First Name
value: Rahul


name: last-name
label: Last Name
value: Sharma

2 个答案:

答案 0 :(得分:1)

您当前的代码仅通过控件元素进行迭代(因为您正在使用getFirstChild, getNextSibling()),因此一旦在控件元素“内部”,您需要检索其正确的后代(标签和值)。一种方法是通过调用getElementsByTagName作为标签和值。

if (e.getTagName().equalsIgnoreCase("control")) {
    String name = e.getAttribute("name");
    System.out.println("It's a " + name + " control!");

    NodeList labels = e.etElementsByTagName("label");
    for (int i = 0;i<labels.getLength();i++) {
        Element labelE = (Element)labels.item(i);
        String label = labelE.getTextContent();
        //do something with the label content;
    }
    ....
    NodeList values = e.etElementsByTagName("value");
    Element valueE = (Element)values.item(0); //seems you always have only one value element
    String value = valueE.get.getTextContent();
    ...
} 

您的xml有多个资源标签,因此有多个标签,您需要决定如何处理它。例如,您可以首先检索资源标记并检查其lang属性以仅处理EN属性。或者总是拿第一个标签。这取决于你。

答案 1 :(得分:0)

    FileInputStream fis = new FileInputStream("test.xml");
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fis);
    NodeList controls = doc.getElementsByTagName("control");
    for (int i = 0; i < controls.getLength(); i++) {
        Element element = (Element)controls.item(i);
        System.out.println(element.getAttribute("name"));
        NodeList resources = element.getElementsByTagName("resources");
        for (int j = 0; j < resources.getLength(); j++) {
            Element resource = (Element) resources.item(j);
            System.out.println(resource.getAttribute("lang"));
            NodeList contents = resource.getChildNodes();
            for (int k = 0; k < contents.getLength(); k++) {
                Node item2 = contents.item(k);
                if (item2 instanceof Element) {
                    Element content = (Element)item2;
                    String tagName = content.getTagName();
                    if (content.getTextContent() != null && !content.getTextContent().isEmpty()) {
                        System.out.println(tagName + ":" + content.getTextContent());
                    }
                }
            }
        }
        NodeList values = element.getElementsByTagName("value");
        if (values.getLength() > 0) {
            Element value = (Element) values.item(0);
            System.out.println(value.getTextContent());
        }
    }

或generante xsd for you xml:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="metadata">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="control" maxOccurs="unbounded" minOccurs="0">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="resources" maxOccurs="unbounded" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="label"/>
                    <xs:element type="xs:string" name="help"/>
                    <xs:element type="xs:string" name="hint"/>
                    <xs:element type="xs:string" name="alert"/>
                  </xs:sequence>
                  <xs:attribute type="xs:string" name="lang" use="optional"/>
                </xs:complexType>
              </xs:element>
              <xs:element type="xs:string" name="value"/>
            </xs:sequence>
            <xs:attribute type="xs:string" name="for" use="optional"/>
            <xs:attribute type="xs:string" name="name" use="optional"/>
            <xs:attribute type="xs:string" name="type" use="optional"/>
            <xs:attribute type="xs:string" name="datatype" use="optional"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

使用JAXB命令生成java类:

xjc test.xsd

并将其用于读取值:

    JAXBContext context = JAXBContext.newInstance(Metadata.class);
    Unmarshaller unmarshaller = context.createUnmarshaller();
    Metadata retorno = unmarshaller.unmarshal(new StreamSource(new File("test.xml")), Metadata.class).getValue();
    List<Metadata.Control> controls = retorno.getControl();
    for (Metadata.Control control : controls) {
        System.out.println(control.getName());
        List<Metadata.Control.Resources> resources = control.getResources();
        for (Metadata.Control.Resources resource : resources) {
            System.out.println(resource.getLabel());
            System.out.println(resource.getHint());
        }
        System.out.println(control.getValue());
    }