在 java 中使用 STAX 解析的一些建议
some suggestions for using STAX Parsing in java
我有一个 XML 文档,它的顶部有数据库配置,如用户名、密码和 URL,然后它有一个名为数据的标签,里面有关于员工的数据和有关部门的数据,我想从 XML 中提取并将其插入数据库。
我已经设法读取 JDBC 配置并将其设置在一个 return 连接并成功工作的 bean 中,但现在我的问题是数据标记如何忽略 JDBC 从 XML 文件配置并读取数据标签并将其插入数据库,我知道我可以像
那样做
if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
currentName = startElement.getName();
if(!currentName.equals("connection-setteings")) ...
但我认为这不是一个好主意,所以有人可以建议一个更好的方法吗?
这是 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<import-request xmlns="http://www.phi01tech.com/tools/data-import" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.phi01tech.com/tools/data-import data-import.xsd ">
<connection-settings>
<username>root</username>
<password>root</password>
<url>jdbc:mysql://localhost:3306/sample</url>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
</connection-settings>
<data>
<departments dept_no="d009" dept_name="Customer Service"/>
<departments dept_no="d005" dept_name="Development"/>
<departments dept_no="d002" dept_name="Finance"/>
<departments dept_no="d003" dept_name="Human Resources"/>
<departments dept_no="d001" dept_name="Marketing"/>
<departments dept_no="d004" dept_name="Production"/>
<departments dept_no="d006" dept_name="Quality Management"/>
<departments dept_no="d008" dept_name="Research"/>
<departments dept_no="d007" dept_name="Sales"/>
<employees emp_no="10001" birth_date="1953-09-02" first_name="Georgi" last_name="Facello" gender="M"
hire_date="1986-06-26"/>
<employees emp_no="10002" birth_date="1964-06-02" first_name="Bezalel" last_name="Simmel" gender="F"
hire_date="1985-11-21"/>
<employees emp_no="10003" birth_date="1959-12-03" first_name="Parto" last_name="Bamford" gender="M"
hire_date="1986-08-28"/>
<employees emp_no="10004" birth_date="1954-05-01" first_name="Chirstian" last_name="Koblick" gender="M"
hire_date="1986-12-01"/>
<employees emp_no="10005" birth_date="1955-01-21" first_name="Kyoichi" last_name="Maliniak" gender="M"
hire_date="1989-09-12"/>
<employees emp_no="10006" birth_date="1953-04-20" first_name="Anneke" last_name="Preusig" gender="F"
hire_date="1989-06-02"/>
<employees emp_no="10007" birth_date="1957-05-23" first_name="Tzvetan" last_name="Zielinski" gender="F"
hire_date="1989-02-10"/>
<employees emp_no="10008" birth_date="1958-02-19" first_name="Saniya" last_name="Kalloufi" gender="M"
hire_date="1994-09-15"/>
</data>
</import-request>
这是我的 java class:
public class STAXParser {
static ConnectionManager connectionManager = new ConnectionManager();
String currentName;
public void parseDocuments() throws IOException, XMLStreamException {
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
try (InputStream stream = Files.newInputStream(Paths.get("emp.xml"))) {
XMLEventReader reader = inputFactory.createXMLEventReader(stream);
while (reader.hasNext()) {
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
currentName = startElement.getName().getLocalPart();
System.out.println(startElement.getName());
Iterator attributes = startElement.getAttributes();
while(attributes.hasNext()) {
//System.out.println(attributes.next());
}
}
if (event.isCharacters()) {
if (!event.asCharacters().isWhiteSpace()) {
String data = event.asCharacters().getData();
checkName(currentName, data.trim());
}
}
}
}
}
private void checkName(String name, String event) {
if (name.equals("url"))
connectionManager.setUrl(event);
else if (name.equals("username"))
connectionManager.setUsername(event);
else if (name.equals("password"))
connectionManager.setPassword(event);
else if (name.equals("driverClassName"))
connectionManager.setDriver(event);
}
public static void main(String[] args) {
STAXParser s = new STAXParser();
try {
s.parseDocuments();
} catch (IOException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
try {
connectionManager.getConnection().toString();
JDBCEmployeeDao d = new JDBCEmployeeDao(connectionManager);
// d.create();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
我发现 XMLStreamReader
更容易使用,因为元素可以在父级的上下文中处理,不像 XMLEventReader
returns 所有事件都在一个平面序列中。
使用 XMLStreamReader
解析 XML 的示例。为简单起见,代码忽略了命名空间。
public static void main(String[] args) throws Exception {
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
Connection connection = null;
try (InputStream stream = Files.newInputStream(Paths.get("src/main/resources/test.xml"))) {
XMLStreamReader reader = inputFactory.createXMLStreamReader(stream);
reader.nextTag(); // Position on root tag
if (! reader.getLocalName().equals("import-request"))
throw new XMLStreamException("Invalid root element: " + reader.getLocalName());
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
switch (reader.getLocalName()) {
case "connection-settings":
connection = parseConnectionSettings(reader);
break;
case "data":
if (connection == null)
throw new XMLStreamException("Missing <connection-settings> before <data>");
parseData(reader, connection);
break;
default:
// ignore unknown content
}
}
} finally {
if (connection != null)
connection.close();
}
}
private static Connection parseConnectionSettings(XMLStreamReader reader) throws Exception {
String username = null, password = null, url = null, driverClassName = null;
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
switch (reader.getLocalName()) {
case "username":
username = reader.getElementText();
break;
case "password":
password = reader.getElementText();
break;
case "url":
url = reader.getElementText();
break;
case "driverClassName":
driverClassName = reader.getElementText();
break;
default:
throw new XMLStreamException("Invalid element in <connection-settings>: " + reader.getLocalName());
}
}
Class.forName(driverClassName);
return DriverManager.getConnection(url, username, password);
}
private static void parseData(XMLStreamReader reader, Connection connection) throws Exception {
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
switch (reader.getLocalName()) {
case "departments":
processDepartments(reader, connection);
break;
case "employees":
processEmployees(reader, connection);
break;
default:
throw new XMLStreamException("Invalid element in <data>: " + reader.getLocalName());
}
}
}
private static void processDepartments(XMLStreamReader reader, Connection connection) throws Exception {
String dept_no = reader.getAttributeValue(null, "dept_no");
String dept_name = reader.getAttributeValue(null, "dept_name");
if (! reader.getElementText().isEmpty())
throw new XMLStreamException("<departments> must be empty element");
// process here
}
private static void processEmployees(XMLStreamReader reader, Connection connection) throws Exception {
// code here
}
我有一个 XML 文档,它的顶部有数据库配置,如用户名、密码和 URL,然后它有一个名为数据的标签,里面有关于员工的数据和有关部门的数据,我想从 XML 中提取并将其插入数据库。
我已经设法读取 JDBC 配置并将其设置在一个 return 连接并成功工作的 bean 中,但现在我的问题是数据标记如何忽略 JDBC 从 XML 文件配置并读取数据标签并将其插入数据库,我知道我可以像
那样做if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
currentName = startElement.getName();
if(!currentName.equals("connection-setteings")) ...
但我认为这不是一个好主意,所以有人可以建议一个更好的方法吗?
这是 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<import-request xmlns="http://www.phi01tech.com/tools/data-import" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.phi01tech.com/tools/data-import data-import.xsd ">
<connection-settings>
<username>root</username>
<password>root</password>
<url>jdbc:mysql://localhost:3306/sample</url>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
</connection-settings>
<data>
<departments dept_no="d009" dept_name="Customer Service"/>
<departments dept_no="d005" dept_name="Development"/>
<departments dept_no="d002" dept_name="Finance"/>
<departments dept_no="d003" dept_name="Human Resources"/>
<departments dept_no="d001" dept_name="Marketing"/>
<departments dept_no="d004" dept_name="Production"/>
<departments dept_no="d006" dept_name="Quality Management"/>
<departments dept_no="d008" dept_name="Research"/>
<departments dept_no="d007" dept_name="Sales"/>
<employees emp_no="10001" birth_date="1953-09-02" first_name="Georgi" last_name="Facello" gender="M"
hire_date="1986-06-26"/>
<employees emp_no="10002" birth_date="1964-06-02" first_name="Bezalel" last_name="Simmel" gender="F"
hire_date="1985-11-21"/>
<employees emp_no="10003" birth_date="1959-12-03" first_name="Parto" last_name="Bamford" gender="M"
hire_date="1986-08-28"/>
<employees emp_no="10004" birth_date="1954-05-01" first_name="Chirstian" last_name="Koblick" gender="M"
hire_date="1986-12-01"/>
<employees emp_no="10005" birth_date="1955-01-21" first_name="Kyoichi" last_name="Maliniak" gender="M"
hire_date="1989-09-12"/>
<employees emp_no="10006" birth_date="1953-04-20" first_name="Anneke" last_name="Preusig" gender="F"
hire_date="1989-06-02"/>
<employees emp_no="10007" birth_date="1957-05-23" first_name="Tzvetan" last_name="Zielinski" gender="F"
hire_date="1989-02-10"/>
<employees emp_no="10008" birth_date="1958-02-19" first_name="Saniya" last_name="Kalloufi" gender="M"
hire_date="1994-09-15"/>
</data>
</import-request>
这是我的 java class:
public class STAXParser {
static ConnectionManager connectionManager = new ConnectionManager();
String currentName;
public void parseDocuments() throws IOException, XMLStreamException {
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
try (InputStream stream = Files.newInputStream(Paths.get("emp.xml"))) {
XMLEventReader reader = inputFactory.createXMLEventReader(stream);
while (reader.hasNext()) {
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
currentName = startElement.getName().getLocalPart();
System.out.println(startElement.getName());
Iterator attributes = startElement.getAttributes();
while(attributes.hasNext()) {
//System.out.println(attributes.next());
}
}
if (event.isCharacters()) {
if (!event.asCharacters().isWhiteSpace()) {
String data = event.asCharacters().getData();
checkName(currentName, data.trim());
}
}
}
}
}
private void checkName(String name, String event) {
if (name.equals("url"))
connectionManager.setUrl(event);
else if (name.equals("username"))
connectionManager.setUsername(event);
else if (name.equals("password"))
connectionManager.setPassword(event);
else if (name.equals("driverClassName"))
connectionManager.setDriver(event);
}
public static void main(String[] args) {
STAXParser s = new STAXParser();
try {
s.parseDocuments();
} catch (IOException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
try {
connectionManager.getConnection().toString();
JDBCEmployeeDao d = new JDBCEmployeeDao(connectionManager);
// d.create();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
我发现 XMLStreamReader
更容易使用,因为元素可以在父级的上下文中处理,不像 XMLEventReader
returns 所有事件都在一个平面序列中。
使用 XMLStreamReader
解析 XML 的示例。为简单起见,代码忽略了命名空间。
public static void main(String[] args) throws Exception {
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
Connection connection = null;
try (InputStream stream = Files.newInputStream(Paths.get("src/main/resources/test.xml"))) {
XMLStreamReader reader = inputFactory.createXMLStreamReader(stream);
reader.nextTag(); // Position on root tag
if (! reader.getLocalName().equals("import-request"))
throw new XMLStreamException("Invalid root element: " + reader.getLocalName());
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
switch (reader.getLocalName()) {
case "connection-settings":
connection = parseConnectionSettings(reader);
break;
case "data":
if (connection == null)
throw new XMLStreamException("Missing <connection-settings> before <data>");
parseData(reader, connection);
break;
default:
// ignore unknown content
}
}
} finally {
if (connection != null)
connection.close();
}
}
private static Connection parseConnectionSettings(XMLStreamReader reader) throws Exception {
String username = null, password = null, url = null, driverClassName = null;
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
switch (reader.getLocalName()) {
case "username":
username = reader.getElementText();
break;
case "password":
password = reader.getElementText();
break;
case "url":
url = reader.getElementText();
break;
case "driverClassName":
driverClassName = reader.getElementText();
break;
default:
throw new XMLStreamException("Invalid element in <connection-settings>: " + reader.getLocalName());
}
}
Class.forName(driverClassName);
return DriverManager.getConnection(url, username, password);
}
private static void parseData(XMLStreamReader reader, Connection connection) throws Exception {
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
switch (reader.getLocalName()) {
case "departments":
processDepartments(reader, connection);
break;
case "employees":
processEmployees(reader, connection);
break;
default:
throw new XMLStreamException("Invalid element in <data>: " + reader.getLocalName());
}
}
}
private static void processDepartments(XMLStreamReader reader, Connection connection) throws Exception {
String dept_no = reader.getAttributeValue(null, "dept_no");
String dept_name = reader.getAttributeValue(null, "dept_name");
if (! reader.getElementText().isEmpty())
throw new XMLStreamException("<departments> must be empty element");
// process here
}
private static void processEmployees(XMLStreamReader reader, Connection connection) throws Exception {
// code here
}