0. 前言
- 参考文档1:使用dom4j读取xml文件的四种方式
- 参考文档2:dom4j解析xml文件
- 参考文档3:String 和 document 的相互转换总结
- 参考文档4: Java SE 6中 XML 数字签名的标准 Java 接口
- 参考文档5:XML Security with Digital Signature in JAVA
1.xml文件的解析
1.1 基本的jdk解析xml的原始api解析
- 声明
- 1.以下代码块要放到一个类中才能运行
- dom类型为:org.w3c.dom.*
- 解析的包:javax.xml.*
- 1.以下代码块要放到一个类中才能运行
1.1.1 输出所xml所有节点内容
/** * 如同js一样的获取节点内容 */
public static void listNl(NodeList nl) {
int len = nl.getLength();
for (int i = 0; i < len; i++) {
Element eltStudent = (Element) nl.item(i);
Node eltName = eltStudent.getElementsByTagName("name").item(0);
Node eltAge = eltStudent.getElementsByTagName("age").item(0);
String name = eltName.getFirstChild().getNodeValue();
String age = eltAge.getFirstChild().getNodeValue();
System.out.print("姓名:");
System.out.println(name);
System.out.print("年龄:");
System.out.println(age);
System.out.println("------------------------");
}
}
@Test
/** * 输出所xml所有节点内容 */
// 示例地址:http://it.chinawin.net/softwaredev/article-16023.html
public void test_ParseXml1Net_01() throws Exception {
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
FileInputStream fis = new FileInputStream(new File(path));
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = f.newDocumentBuilder();
Document doc = builder.parse(fis);
NodeList nl = doc.getElementsByTagName("student");
listNl(nl);
}
1.1.2 将字符串转化为xml文件
/** * 将字符串转化为xml文件 *//***/
@Test
public void test_String2Xml() throws Exception {
// String xmlStr = new String("ASDFADADSD");//报错:[Fatal Error] :1:1: 前言中不允许有内容。
String xmlStr = new String("<?xml version=\"1.0\" encoding=\"GB2312\"?><students><student sn=\"01\"><name>张三</name><age>18</age></student><student sn=\"02\"><name>李四</name><age>20</age></student></students>");
StringReader sr = new StringReader(xmlStr);
InputSource is = new InputSource(sr);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
System.out.println(doc.getClass());//com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl
}
1.1.3 将xml文件转化为字符串
/** * 读取本地文件xml文件为Document对象 */
public static Document test_readXml() throws Exception {
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
FileInputStream fis = new FileInputStream(new File(path));
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = f.newDocumentBuilder();
Document doc = builder.parse(fis);
System.out.println(doc);// ★★[#document: null]注意这里不是打印出来xml文件内容,并不代表没有读到xml文件
return doc;
}
@Test
/** * 将xml文件转化为字符串 */
public void test_Xml2String() throws Exception {
Document doc = this.test_readXml();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty("encoding","UTF-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
t.transform(new DOMSource(doc),new StreamResult(bos));
String xmlStr = bos.toString();
System.out.println(xmlStr);
}
1.2 使用dom4解析xml
- 声明
- 以下代码块要放到一个类中才能运行
- dom类型和解析的包为:org.dom4j.*
- ★注意:javax.xml.parsers中的和dom4j中的两种形式的Document不能转换
- 以下代码块要放到一个类中才能运行
1.2.1将String转换为Dom4j的Document类对象
/** * 所以在应用时只能用一套xml解析方案,不能交替使用,否则报:ClassCastException异常 * dom4j具体细节操作:参见http://www.cnblogs.com/liuling/archive/2013/02/05/dom4jxml.html *//***/
@Test
public void test_String2Xml_dom4j() throws DocumentException {
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
String xmlStr = new String("<?xml version=\"1.0\" encoding=\"GB2312\"?><students><student sn=\"01\"><name>张三</name><age>18</age></student><student sn=\"02\"><name>李四</name><age>20</age></student></students>");
Document document = DocumentHelper.parseText(xmlStr);// 必须引入dom4j的Document
}
1.2.2 最普通的方法得到xml文件信息
@Test
/** * 方法1:将xml文件看成普通文本文件输出字符信息 */
public void test_OrdTextReadXml() throws Exception {
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
File f = new File(path);
InputStream in = new FileInputStream(f);
byte[] b = new byte[1024];
in.read(b);
in.close();
System.out.println(new String(b));
}
@Test
/** * ★★方法2:解析后读取xml文件中所有节点信息, */
public void test_Xml2String_dom4j() throws Exception {
SAXReader sr = new SAXReader();// 获取读取xml的对象。
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
Document doc = sr.read(path);// 得到xml所在位置。然后开始读取。并将数据放入doc中
Element el_root = doc.getRootElement();// 向外取数据,获取xml的根节点。
Iterator it = el_root.elementIterator();// 从根节点下依次遍历,获取根节点下所有子节点
while (it.hasNext()) {// 遍历该子节点
Object o = it.next();// 再获取该子节点下的子节点
Element el_row = (Element) o;
String s = el_row.getText();
Iterator it_row = el_row.elementIterator();
while (it_row.hasNext()) {// 遍历节点
Element el_ename = (Element) it_row.next();// 获取该节点下的所有数据。
System.out.println(el_ename.getText());
}
}
}
@Test
/** * 方法三:使用elements方法进行xml的读取,相当于条件查询,可以根据不同的节点,利用for循环查询该节点下所有的数据。 * 依据不同的xml文件而定 */
public void test_ByElement() throws Exception {
SAXReader sr = new SAXReader();// 获取读取方式
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
Document doc = sr.read(path);// 读取xml文件,并且将数据全部存放到Document中
Element root = doc.getRootElement();// 获取根节点
List list = root.elements("student");// 根据根节点,将根节点下 student中的所有数据放到list容器中。
for (Object obj : list) {// 这种遍历方式,是jdk1.5以上的版本支持的遍历方式
Element row = (Element) obj;
List list_name = row.elements("name");// 获取name节点下所有的内容,存入list_row容器中
for (Object objempno : list_name) {
Element el_empno = (Element) objempno;
System.out.println(el_empno.getName() + ": " + el_empno.getText());// 获取节点下的数据。
}
}
}
@Test
/** * 方法四:使用selectNodes()方法 */
public void test_bySelectNode() throws Exception {
String elementpath = new String("name");// 使用selectNodes获取所要查询xml的节点。
SAXReader sr = new SAXReader();
String path = "D:\\workspace\\java_base\\src\\hw\\learn\\simple\\xml\\student.xml";
Document doc = sr.read(path);
List list = doc.selectNodes(elementpath);
for (Object obj : list) {// 遍历节点,获取节点内数据。
Element el = (Element) obj;
System.out.println(el.getText());
}
}
2. xml签名
2.1 应用场景
xml作为一种通用跨平台的数据传输的方式,其安全性也受到重视,很多应用或商家在用xml文件之间传输信息时通常要对xml文件进行签名,以确定数据的完整性,以及防篡改。下面是在工作中遇到的签名xml文件的一种方式。2.2 应用过程
银行身份验证服务接口测试流程
/** 获取私钥 */
PrivateKey priKey=CertHelper.getPrivateKey();
/** 签名XML文档 */
Document signDoc=CertHelper.signXmlDoc(srcDoc,priKey);
/** 发送请求到网银服务器 */
String result=CertHelper.sendHTTPRequest(signDoc);
- 获取公钥、验证返回数据
/** * 验证签名数据 */
boolean checkResult=CertHelper.isXmlValid(doc,getPubKey());
- 处理返回数据:验证用户身份信息的正确性
2.3 签名代码
public class SignXml {
// 参考文档:http://www.javacodegeeks.com/2013/10/xml-security-with-digital-signature-in-java.html
/** * @param doc 待签名的xml文档 * @param privateKey 用于对xml签名的私钥 * @return 已签名的xml文档 */
public static Document signXmlDoc(Document doc,PrivateKey privateKey) throws Exception {
// 创建XML签名工厂
XMLSignatureFactory xmlSigFactory = XMLSignatureFactory.getInstance("DOM");
DOMSignContext domSignCtx = new DOMSignContext(privateKey,doc.getDocumentElement());
System.out.println(domSignCtx);
javax.xml.crypto.dsig.Reference ref = null;
SignedInfo signedInfo = null;
try {
ref = xmlSigFactory.newReference("#CUSTINFOREQ",xmlSigFactory.newDigestMethod(DigestMethod.SHA1,null),Collections.singletonList(xmlSigFactory.newTransform(Transform.ENVELOPED,(TransformParameterSpec) null)),null,null);
signedInfo = xmlSigFactory.newSignedInfo(xmlSigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,(C14NMethodParameterSpec) null),xmlSigFactory.newSignatureMethod(SignatureMethod.RSA_SHA1,Collections.singletonList(ref));
System.out.println(signedInfo);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
KeyInfo ki = null;
// 创建新的XML签名
XMLSignature xmlSignature = xmlSigFactory.newXMLSignature(signedInfo,ki);
try {
// 对文档签名
xmlSignature.sign(domSignCtx);
// ★打印出来xml文档:查看签名信息!【org.dom.Document->String】
System.out.println("#Begin:get signedXmlDoc********************************");
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty("encoding","GB23121");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
t.transform(new DOMSource(doc),new StreamResult(bos));
String xmlStr = bos.toString();
System.out.println(xmlStr);
System.out.println("#End:get signedXmlDoc********************************");
return doc;
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
应用