XML、JSON处理技术全面解析
1. XSLT 转换 XML 文档
XSLT 是用于转换和格式化 XML 文档的语言族。它借助 XSLT 处理器和样式表来完成工作。XSLT 处理器是一种软件组件,它将 XSLT 样式表(基于 XML 的模板,包含内容和转换指令)应用于输入文档(不修改文档),并将转换结果复制到结果树,结果树可输出到文件或输出流,甚至可输入到另一个 XSLT 处理器进行额外转换。
要将源转换为结果,需调用
Transformer
的
void transform(Source xmlSource, Result outputTarget)
方法。
以下是一个将
books.xml
内容转换为 HTML 的样式表示例:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/books">
<html>
<head>
<title>Books</title>
</head>
<body>
<xsl:for-each select="book">
<h2>
<xsl:value-of select="normalize-space(title/text())"/>
</h2>
ISBN: <xsl:value-of select="@isbn"/><br/>
Publication Year: <xsl:value-of select="@pubyear"/><br/>
<br/><xsl:text>
</xsl:text>
<xsl:for-each select="author">
<xsl:value-of select="normalize-space(text())"/><br/><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
下面是使用该样式表将书籍 XML 转换为 HTML 的 Java 应用示例:
import java.io.FileReader;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class MakeHTML
{
public static void main(String[] args)
{
try
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("books.xml");
TransformerFactory tf = TransformerFactory.newInstance();
StreamSource ssStyleSheet;
ssStyleSheet = new StreamSource(new FileReader("books.xsl"));
Transformer t = tf.newTransformer(ssStyleSheet);
t.setOutputProperty(OutputKeys.METHOD, "html");
t.setOutputProperty(OutputKeys.INDENT, "yes");
Source source = new DOMSource(doc);
Result result = new StreamResult(System.out);
t.transform(source, result);
}
catch (IOException ioe)
{
System.err.println("IOE: " + ioe);
}
catch (FactoryConfigurationError fce)
{
System.err.println("FCE: " + fce);
}
catch (ParserConfigurationException pce)
{
System.err.println("PCE: " + pce);
}
catch (SAXException saxe)
{
System.err.println("SAXE: " + saxe);
}
catch (TransformerConfigurationException tce)
{
System.err.println("TCE: " + tce);
}
catch (TransformerException te)
{
System.err.println("TE: " + te);
}
catch (TransformerFactoryConfigurationError tfce)
{
System.err.println("TFCE: " + tfce);
}
}
}
2. JSON 基础介绍
JSON(JavaScript Object Notation)是一种独立于语言的数据格式,它将 JSON 对象表示为人类可读的属性列表。JSON 源自 JavaScript 的非严格子集。
JSON 数据格式将 JSON 对象表示为用花括号分隔、逗号分隔的属性列表。JSON 支持六种类型:数字、字符串、布尔值、数组、对象和 null,并且不支持注释。
要将 JSON 对象解析为等效的 JavaScript 对象,可调用
JSON
对象的
parse()
方法,并将待解析的文本作为该方法的参数。
JSON Schema 是一种用于定义 JSON 对象的结构、内容和(在一定程度上)语义的语法语言。创建模式时,可通过将属性名称放入分配给模式的
required
属性名的数组中,来标识模式验证的 JSON 对象中必须存在的属性。
以下是一个产品的 JSON 对象示例:
{
"name": "hammer",
"price": 20
}
以下是验证产品对象的模式示例:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product",
"description": "A product",
"type": "object",
"properties":
{
"name":
{
"description": "A product name",
"type": "string"
},
"price":
{
"description": "A product price",
"type": "number",
"minimum": 1
}
},
"required": ["name", "price"]
}
3. mJson 解析和创建 JSON 对象
mJson 是一个基于 Java 的小型 JSON 库,用于在 JSON 对象和 Java 对象之间进行相互转换。
Json
类描述了一个 JSON 对象或其一部分,包含
Schema
和
Factory
接口、50 多个方法和其他成员。
Json
用于读取和解析外部 JSON 对象的方法有
Json read(String s)
、
Json read(URL url)
和
Json read(CharacterIterator ci)
,这些方法也可解析较小的 JSON 片段,如不同类型值的数组。
Json
提供的创建 JSON 对象的方法有
Json array()
、
Json array(Object... args)
、
Json make(Object anything)
、
Json nil()
、
Json object()
和
Json object(Object... args)
。
以下是一个展示
Json
的
dup()
和
pad()
方法的示例:
import mjson.Json;
public class mJsonDemo
{
public static void main(String[] args)
{
Json json1 = Json.read("{\"name\": \"John Doe\"}");
Json json2 = json1.dup();
System.out.println(json1);
System.out.println();
System.out.println(json2);
System.out.println();
System.out.printf("json1 == json2: %b%n", json1 == json2);
System.out.printf("json1.equals(json2): %b%n", json1.equals(json2));
System.out.println();
System.out.println(json1.pad("func"));
/*
The following output is generated:
{"name":"John Doe"}
{"name":"John Doe"}
json1 == json2: false
json1.equals(json2): true
func({"name":"John Doe"});
*/
}
}
4. Gson 解析和创建 JSON 对象
Gson 是一个基于 Java 的小型库,用于解析和创建 JSON 对象,由 Google 开发并公开可用。
Gson 的包包括
com.google.gson
(提供对
Gson
主类的访问)、
com.google.gson.annotations
(提供与 Gson 一起使用的注解类型)、
com.google.gson.reflect
(提供从泛型类型获取类型信息的实用类)和
com.google.gson.stream
(提供用于读写 JSON 编码值的实用类)。
获取
Gson
对象有两种方式:调用
Gson()
构造函数或在
GsonBuilder
对象上调用
create()
方法。
Gson 为
java.lang.Enum
、
java.util.Map
、
java.net.URL
、
java.net.URI
、
java.util.Locale
、
java.util.Date
、
java.math.BigDecimal
和
java.math.BigInteger
等类型提供默认的序列化和反序列化。
要启用漂亮打印,可调用
GsonBuilder
的
setPrettyPrinting()
方法。默认情况下,Gson 排除
transient
或
static
字段的序列化和反序列化。
以下是一个使用 Gson 序列化和反序列化正确暴露的
static
字段的示例:
import java.lang.reflect.Modifier;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
public class GsonDemo
{
static class SomeClass
{
transient int id;
@Expose(serialize = true, deserialize = true)
transient String password;
@Expose(serialize = false, deserialize = false)
int field1;
@Expose(serialize = false, deserialize = true)
int field2;
@Expose(serialize = true, deserialize = false)
int field3;
@Expose(serialize = true, deserialize = true)
int field4;
@Expose(serialize = true, deserialize = true)
static int field5;
static int field6;
}
public static void main(String[] args)
{
SomeClass sc = new SomeClass();
sc.id = 1;
sc.password = "abc";
sc.field1 = 2;
sc.field2 = 3;
sc.field3 = 4;
sc.field4 = 5;
sc.field5 = 6;
sc.field6 = 7;
GsonBuilder gsonb = new GsonBuilder();
gsonb.excludeFieldsWithoutExposeAnnotation();
gsonb.excludeFieldsWithModifiers(Modifier.TRANSIENT);
Gson gson = gsonb.create();
String json = gson.toJson(sc);
System.out.println(json);
SomeClass sc2 = gson.fromJson(json, SomeClass.class);
System.out.printf("id = %d%n", sc2.id);
System.out.printf("password = %s%n", sc2.password);
System.out.printf("field1 = %d%n", sc2.field1);
System.out.printf("field2 = %d%n", sc2.field2);
System.out.printf("field3 = %d%n", sc2.field3);
System.out.printf("field4 = %d%n", sc2.field4);
System.out.printf("field5 = %d%n", sc2.field5);
System.out.printf("field6 = %d%n", sc2.field6);
}
}
5. JsonPath 提取 JSON 属性值
JsonPath 是一种声明式查询语言,用于选择和提取 JSON 文档的属性值。它基于 XPath 1.0。
表示根 JSON 对象的运算符是
$
,可使用点符号和方括号符号指定 JsonPath 表达式。
@
运算符表示由过滤谓词处理的当前节点。
JsonPath 的
JsonPath compile(String jsonPath, Predicate... filters)
静态方法将存储在
jsonPath
引用的字符串中的 JsonPath 表达式编译为
JsonPath
对象,以提高表达式重用时的性能。
以下是一个提取和输出最大、最小和平均数值的示例:
import com.jayway.jsonpath.JsonPath;
public class JsonPathDemo
{
public static void main(String[] args)
{
String json =
"{" +
" \"numbers\": [10, 20, 25, 30]" +
"}";
String expr = "$.numbers.max()";
double d = JsonPath.read(json, expr);
System.out.printf("Max value = %f%n", d);
expr = "$.numbers.min()";
d = JsonPath.read(json, expr);
System.out.printf("Min value = %f%n", d);
expr = "$.numbers.avg()";
d = JsonPath.read(json, expr);
System.out.printf("Average value = %f%n", d);
}
}
6. 总结
在处理 XML 和 JSON 数据时,不同的技术和工具各有优势。XSLT 适用于 XML 文档的转换和格式化,能将 XML 数据转换为各种格式,如 HTML。JSON 以其简洁和跨语言的特性,成为数据交换的常用格式,而 mJson、Gson 和 JsonPath 则为 JSON 数据的处理提供了强大的支持。mJson 提供了简单的 JSON 对象解析和创建功能,Gson 则在序列化和反序列化方面表现出色,支持自定义处理和泛型。JsonPath 则让我们可以方便地从 JSON 文档中提取所需的属性值。
通过合理运用这些技术和工具,我们可以高效地处理和转换 XML 和 JSON 数据,满足不同场景下的需求。例如,在 Web 开发中,可使用 XSLT 将服务器端的 XML 数据转换为 HTML 页面,使用 Gson 实现前后端之间的 JSON 数据交互,使用 JsonPath 从返回的 JSON 数据中提取关键信息。在数据处理和分析领域,这些技术也能帮助我们对大量的 XML 和 JSON 数据进行处理和转换,为后续的分析工作提供支持。
在实际应用中,我们需要根据具体的需求和场景选择合适的技术和工具,同时注意处理过程中的错误和异常情况,确保数据处理的准确性和稳定性。例如,在使用 Gson 进行序列化和反序列化时,要注意对
transient
和
static
字段的处理,以及自定义序列化和反序列化的实现。在使用 JsonPath 时,要正确编写表达式,避免出现错误的结果。
总之,XML 和 JSON 处理技术是现代软件开发中不可或缺的一部分,掌握这些技术能让我们在数据处理和交换方面更加得心应手。
XML、JSON处理技术全面解析
7. 技术对比与选择
为了更好地选择适合的技术,我们可以对上述介绍的 XML 和 JSON 处理技术进行对比。以下是一个简单的对比表格:
| 技术 | 适用场景 | 优点 | 缺点 |
| ---- | ---- | ---- | ---- |
| XSLT | XML 文档转换和格式化,如将 XML 转换为 HTML | 能灵活定义转换规则,基于 XML 模板,易于理解和维护 | 对于复杂的转换逻辑,样式表可能变得复杂 |
| mJson | 简单的 JSON 对象解析和创建,对性能要求不高的场景 | 轻量级,API 简单易用 | 功能相对有限,缺乏一些高级特性 |
| Gson | 需要进行复杂序列化和反序列化,支持自定义处理和泛型的场景 | 功能强大,支持多种类型的默认处理,可自定义序列化和反序列化逻辑 | 学习成本相对较高,对于简单场景可能过于复杂 |
| JsonPath | 从 JSON 文档中提取特定属性值 | 基于路径表达式,能方便地选择和提取数据 | 表达式编写需要一定的学习成本,错误的表达式可能导致结果不准确 |
在选择技术时,我们可以参考以下流程:
graph LR
A[确定数据类型] --> B{是 XML 数据吗?}
B -- 是 --> C{需要转换格式吗?}
C -- 是 --> D[使用 XSLT]
C -- 否 --> E[其他 XML 处理技术]
B -- 否 --> F{需要解析和创建 JSON 对象吗?}
F -- 是 --> G{需求简单吗?}
G -- 是 --> H[使用 mJson]
G -- 否 --> I{需要自定义处理吗?}
I -- 是 --> J[使用 Gson]
I -- 否 --> H
F -- 否 --> K{需要提取 JSON 属性值吗?}
K -- 是 --> L[使用 JsonPath]
K -- 否 --> M[其他 JSON 处理技术]
8. 实际应用案例分析
以下通过几个实际应用案例,进一步说明这些技术的使用。
8.1 Web 开发中的数据展示
在一个 Web 应用中,服务器端存储了一些书籍信息的 XML 数据,需要将这些数据展示在网页上。我们可以使用 XSLT 将 XML 数据转换为 HTML 页面。
-
步骤
:
1. 创建 XSLT 样式表,定义 XML 到 HTML 的转换规则,如前面提到的
books.xsl
。
2. 在服务器端,使用 Java 代码读取 XML 文件和 XSLT 样式表,进行转换并输出到客户端,如
MakeHTML
示例。
3. 客户端浏览器接收到 HTML 页面并显示。
8.2 前后端数据交互
在前后端分离的开发模式中,前后端通常使用 JSON 进行数据交互。假设前端需要向后端请求产品信息,后端返回 JSON 数据。
-
后端
:使用 Gson 将 Java 对象序列化为 JSON 数据。
import com.google.gson.Gson;
class Product {
String name;
double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
}
public class BackendExample {
public static void main(String[] args) {
Product product = new Product("hammer", 20);
Gson gson = new Gson();
String json = gson.toJson(product);
System.out.println(json);
}
}
-
前端
:使用 JavaScript 的
JSON.parse()方法将接收到的 JSON 字符串解析为 JavaScript 对象。
let jsonString = '{"name":"hammer","price":20}';
let product = JSON.parse(jsonString);
console.log(product.name);
console.log(product.price);
8.3 数据提取与分析
在数据分析场景中,我们可能会从大量的 JSON 数据中提取特定的属性值进行分析。例如,有一个包含多个学生成绩的 JSON 数据,我们需要提取所有学生的平均分。
-
步骤
:
1. 定义 JsonPath 表达式,如
$.students[*].scores.avg()
。
2. 使用 JsonPath 库读取 JSON 数据并执行表达式。
import com.jayway.jsonpath.JsonPath;
public class ScoreAnalysis {
public static void main(String[] args) {
String json = "{\"students\":[{\"scores\":[80, 90, 70]},{\"scores\":[85, 95, 75]}]}";
String expr = "$.students[*].scores.avg()";
Object result = JsonPath.read(json, expr);
System.out.println(result);
}
}
9. 常见错误处理与注意事项
在使用这些技术时,我们可能会遇到一些常见的错误和问题,以下是一些处理建议和注意事项。
9.1 XSLT
- 样式表语法错误 :样式表中的 XML 语法错误会导致转换失败。在编写样式表时,要仔细检查语法,可使用 XML 验证工具进行验证。
- 转换逻辑错误 :复杂的转换逻辑可能导致结果不符合预期。可以通过调试样式表,逐步检查转换过程。
9.2 mJson
-
空指针异常
:在使用
Json对象时,如果对象为空,调用其方法可能会导致空指针异常。在使用前要进行空值检查。 - 类型不匹配 :在获取或设置属性值时,要确保类型匹配,否则可能会抛出异常。
9.3 Gson
-
transient和static字段处理不当:默认情况下,Gson 排除transient或static字段的序列化和反序列化。如果需要处理这些字段,要使用相应的注解和配置。 -
自定义序列化和反序列化错误:自定义实现
JsonSerializer和JsonDeserializer时,要确保逻辑正确,否则可能会导致序列化和反序列化结果错误。
9.4 JsonPath
- 表达式编写错误:错误的 JsonPath 表达式会导致提取的数据不准确或抛出异常。在编写表达式时,要仔细检查语法和逻辑,可使用在线工具进行测试。
10. 未来发展趋势
随着软件开发的不断发展,XML 和 JSON 处理技术也在不断演进。
对于 XML,虽然在一些新兴领域的使用有所减少,但在一些传统行业和特定场景中,如企业级应用、数据交换标准等,仍然具有重要地位。未来,XML 处理技术可能会更加注重性能优化和与其他技术的集成。
JSON 作为一种轻量级的数据交换格式,在 Web 开发、移动应用开发等领域得到了广泛应用。未来,JSON 可能会在以下方面有所发展:
-
更强大的模式验证
:JSON Schema 可能会进一步发展,提供更丰富的验证规则和语义支持。
-
与其他技术的深度融合
:JSON 可能会与人工智能、大数据等技术进行更深度的融合,为数据处理和分析提供更好的支持。
总之,XML 和 JSON 处理技术在未来仍然会是软件开发中重要的组成部分,我们需要不断关注和学习这些技术的发展,以适应不断变化的需求。
通过全面了解 XML 和 JSON 处理技术,我们可以根据实际需求选择合适的技术,高效地处理和转换数据,为软件开发和数据处理工作提供有力支持。同时,我们也要注意处理过程中的错误和异常,不断提高数据处理的准确性和稳定性。在未来的学习和实践中,我们可以进一步探索这些技术的高级特性和应用场景,不断提升自己的技术水平。
超级会员免费看
1327

被折叠的 条评论
为什么被折叠?



