编写一个包含多个元素的XML,这些元素又包含多个元素

时间:2014-04-11 09:13:17

标签: java xml xsd

这里我有一个包含多名学生和多位老师的XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
  <students>
    <student id="student1">
      <name>Alan</name>
      <age>11</age>
      <dob>01/01/2001</dob>
      <grade>A+</grade>
    </student>
    <student id="student2">
      <name>Bob</name>
      <age>22</age>
      <dob>02/02/2002</dob>
      <grade>A</grade>
    </student>
  </students>

  <teachers>
    <teacher id="teacher3">
      <name>David</name>
      <age>33</age>
      <dob>03/03/2003</dob>
      <subject>Maths</subject>
    </teacher>
    <teacher id="teacher4">
      <name>Ellen</name>
      <age>44</age>
      <dob>04/04/2004</dob>
      <subject>English</subject>
    </teacher>
  </teachers>
</users>

我有一个Java应用程序,可以正常读取此文件。然而,就写作而言,它是一个混乱的混乱。它与应用程序在读取和写入名称/年龄/ dob时的行为一致,但在我尝试写入成绩/主题的那一刻,它失去了控制权。

我通过打印列表中每个项目的名称来测试它;并按预期打印:

  • 艾伦
  • 鲍勃
  • 大卫
  • 埃伦

我通过打印列表中每个项目的年龄来再次测试;再次,它按预期打印:

  • 阿伦
  • 11
  • 鲍勃
  • 22
  • 大卫
  • 33
  • 埃伦
  • 44

但是这次,我尝试打印主题:

  • 阿伦
  • 数学
  • 鲍勃
  • 大卫

在打印第一位老师后打印学生下的科目并打破,我试图了解原因。因此,对于我的最终测试,我决定打印索引0处的所有元素,包括成绩和主题,看看会发生什么:

  • 艾伦
  • 11
  • 01/01/2001
  • A +
  • 数学

主题应该在索引2,而不是0,那么为什么这样做呢?为什么系统读取和写入正确直到这一点?只是包装,这是我的XSD,用于在读取之前验证XML。

<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
  <xs:element name="users">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="students" minOccurs='1' maxOccurs='unbounded'/>
    <xs:element ref="teachers" minOccurs='1' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="students">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="student" minOccurs='1' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="student">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="name" minOccurs='0' maxOccurs='1'/>
        <xs:element ref="age" minOccurs='0' maxOccurs='1'/>
        <xs:element ref="dob" minOccurs='0' maxOccurs='1'/>
    <xs:element ref="grade" minOccurs='0' maxOccurs='1'/>
      </xs:sequence>
      <xs:attribute name="id" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="teachers">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="teacher" minOccurs='1' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="teacher">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="name" minOccurs='0' maxOccurs='1'/>
        <xs:element ref="age" minOccurs='0' maxOccurs='1'/>
        <xs:element ref="dob" minOccurs='0' maxOccurs='1'/>
    <xs:element ref="subject" minOccurs='0' maxOccurs='1'/>
      </xs:sequence>
      <xs:attribute name="id" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="name" type='xs:string'/>
  <xs:element name="age" type='xs:string'/>
  <xs:element name="dob" type='xs:string'/>
  <xs:element name="grade" type='xs:string'/>
  <xs:element name="subject" type='xs:string'/>
</xs:schema>

道歉,我忘了包含以下编码。以下是将新数据写入XML文件的编码:

void updateXML(int index, String fields[]) {

  try {

    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
    Document doc = docBuilder.parse(new File(fileName));

    doc.getElementsByTagName("name").item(index).setTextContent(fields[0]);
    doc.getElementsByTagName("age").item(index).setTextContent(fields[1]);
    doc.getElementsByTagName("dob").item(index).setTextContent(fields[2]);

    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer();
    DOMSource source = new DOMSource(doc);
    StreamResult result = new StreamResult(new File(fileName));

    transformer.transform(source, result);

  } catch (Exception error) {

    error.getMessage();
  }
}

目前它正常工作,它可以正确保存数据。但由于我遇到的问题,不包括成绩/科目。


这是创建对象的类:

class Model extends DefaultHandler {

String          fileName;
ArrayList<User> listOfUsers;
Student         student;
Teacher         teacher;

boolean blnStudent  = false;
boolean blnTeacher  = false;
boolean blnName     = false;
boolean blnAge      = false;
boolean blnDOB      = false;
boolean blnGrade    = false;
boolean blnSubject  = false;

Model() {

    fileName    = "school.xml";
    listOfUsers = new ArrayList<User>();
}

ArrayList<User> getListOfUsers() {

    if (validateXML() == true) {

        try {

            SAXParserFactory factory    = SAXParserFactory.newInstance();
            SAXParser parser            = factory.newSAXParser();

            parser.parse(new File(fileName), this);

        } catch (Exception error) {

            error.getMessage();
        }
    }

    return listOfUsers;
}

boolean validateXML() {

    try {

        SchemaFactory factory   = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
        Schema schema           = factory.newSchema(new File("school.xsd"));
        Validator validator     = schema.newValidator();
        Source source           = new StreamSource(new File(fileName));

        validator.validate(source);
        return true;

    } catch (Exception error) {

        error.getMessage();
        return false;
    }
}

public void startElement(String uri, String localName, String tagName, Attributes attributes) throws SAXException {

    if (tagName.equalsIgnoreCase("student")) {

        student     = new Student(attributes.getValue("id"));
        blnStudent  = true;

    } else if (tagName.equalsIgnoreCase("teacher")) {

        teacher     = new Teacher(attributes.getValue("id"));
        blnTeacher  = true;

    } else if (tagName.equalsIgnoreCase("name")) {

        blnName = true;

    } else if (tagName.equalsIgnoreCase("age")) {

        blnAge = true;

    } else if (tagName.equalsIgnoreCase("dob")) {

        blnDOB = true;

    } else if (tagName.equalsIgnoreCase("grade")) {

        blnGrade = true;

    } else if (tagName.equalsIgnoreCase("subject")) {

        blnSubject = true;
    }
}

public void endElement(String uri, String localName, String tagName) throws SAXException {

    if (tagName.equalsIgnoreCase("student")) {

        listOfUsers.add(student);

    } else if (tagName.equalsIgnoreCase("teacher")) {

        listOfUsers.add(teacher);
    }
}

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

    if (blnStudent) {

        if (blnName) {

            student.setName(new String(ch, start, length));
            blnName = false;

        } else if (blnAge) {

            student.setAge(new String(ch, start, length));
            blnAge = false;

        } else if (blnDOB) {

            student.setDOB(new String(ch, start, length));
            blnDOB = false;

        } else if (blnGrade) {

            student.setGrade(new String(ch, start, length));
            blnGrade    = false;
            blnStudent  = false;
        }

    } else if (blnTeacher) {

        if (blnName) {

            teacher.setName(new String(ch, start, length));
            blnName = false;

        } else if (blnAge) {

            teacher.setAge(new String(ch, start, length));
            blnAge = false;

        } else if (blnDOB) {

            teacher.setDOB(new String(ch, start, length));
            blnDOB = false;

        } else if (blnSubject) {

            teacher.setSubject(new String(ch, start, length));
            blnSubject = false;
            blnTeacher = false;
        }
    }
}

void updateXML(int index, String fields[]) {

    try {

        DocumentBuilderFactory docFactory   = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder          = docFactory.newDocumentBuilder();
        Document doc                        = docBuilder.parse(new File(fileName));

        doc.getElementsByTagName("name")    .item(index).setTextContent(fields[0]);
        doc.getElementsByTagName("age")     .item(index).setTextContent(fields[1]);
        doc.getElementsByTagName("dob")     .item(index).setTextContent(fields[2]);
        // IF STUDENT
        doc.getElementsByTagName("grade")   .item(index).setTextContent(fields[3]);
        // ELSE TEACHER

        TransformerFactory factory  = TransformerFactory.newInstance();
        Transformer transformer     = factory.newTransformer();
        DOMSource source            = new DOMSource(doc);
        StreamResult result         = new StreamResult(new File(fileName));

        transformer.transform(source, result);

    } catch (Exception error) {

        error.getMessage();
    }
}
}

1 个答案:

答案 0 :(得分:0)

问题在于这些要素不会影响用户自己;它们只能通过创建它们的数量来调用。例如,当我设置用户名时:

doc.getElementsByTagName("name").item(0).setTextContent("Alan Zero");

我不是要求系统set the FIRST USER'S name value,我要求系统做的是set the FIRST NAME value。因此,只要每个用户创建完全相同数量的字段,这就不会有问题,因为每个字段都会自动分配给各自的用户。例如:

  • (0)Alan Zero
  • (1)Bob One
  • (2)Chris Two

如果他们每个人都有成绩:

  • (0)A
  • (1)B
  • (2)C

但是在我的示例中,某些用户可以拥有成绩值,而某些用户可以拥有主题值。结果,索引值变得不一致。例如:

  • (0)(学生)Alan Zero
  • (1)(老师)Bob One
  • (2)(学生)Chris Two

因此,等级/主题值将被编入索引:

  • (0)A
  • (1)B

  • (0)数学

为了纠正这个问题,我需要找到一种方法来分别绑定每个元素。谢谢大家的快速回复。