XML解析

XML的特点

XML与操作系统、编程语言的开发平台都无关;

规范统一,实现不同系统之间的数据交互。

XML技术应用广泛,最基本的如网站,应用程序的配置信息一般采用XML文件描述。

 

XML的文档结构

简单xml文档结构如下图:

第一行是 XML 声明。它定义 XML 的版本和所使用的编码 

下一行描述根元素

 

然后是4个子元素的描述

 

最后是根元素结尾

 

父元素拥有子元素。相同层级上的子元素成为同胞。

 

表示书店的xml文档

 

与上述xml对应的结构图

 

1. XML声明

<?xml version="1.0" encoding=”utf-8”?>表示XML声明

version:文档符合XML1.0规范

encoding:文档字符编码,默认为“UTF-8”

对于任何一个XMl文档,其声明部分是固定格式

 

2. 标签

非空的元素一定是成对的标记

<起始标记>

<></>

</结束标记>

空元素:起始标记和接受标记是紧挨着的,空行和空格都没有,一般学成单标记的形式

<起始标记></结束标记>

–例如:“马牛逼"中就是开始标签,就是结束标签,”马牛逼“就是标签描述的内容,表示姓名信息

 

3. 元素

元素由开始标签、结束标签和元素内容组成,开始标签由”<“+”元素名“+">”组成·,结束标签

由”<“+”元素名“+">”直接多了一个“/”。

 

元素的命名规范规则如下

名称中可以包含字母、数字以及其它一些可见字符

区分大小写

不能以数字或"_" (下划线)开头

不能以xml(或XML、或Xml 等)开头

不能包含空格。

4. 根元素

每个XMl文档必须有且仅有一个根元素,如“".

 

根元素的特点

根元素是一个完全包括文档中其他所有元素的元素

根元素的起始标签要放在其他所有元素的起始标签之前

根元素的结束标签要放在所有其他元素的结束标签之后

 

5.属性

xml是标记型文档,可以有属性,如:<person id="aaa"></person>

属性定义的要求:

  1. 一个标签上可以有多个属性
  2. 属性值要用引号(单引号或双引号)引起来
  3. 属性名称的命名规范与标签名称的命名规范一样

语法:

< 元素名 属性名 =“ 属性值 ”>

 

6. XML中的特殊字符的处理

XML中的预定义实体和特殊字符的对应关系

特殊字符

实体名称

<    

&lt;   

>  

&gt; 

&  

&amp;  

"  

&quot; 

’   

&apos;  

2. 在元素的文本中使用CDATA交处理。CDATA节中的所有字符都会被当作元素字符数据的常量部分,而不是XML标签

 

语法:

 

<! [CDATA[

要显示的字符

] ]>

 

7.XML中的注释

注释的语法

 

语法:

 

<!--注释内容-->

 

8.格式良好的XML文档

 

遵守如下规则的XML文档,称为格式良好的XML文档。

 

  1)必须有xml的声明,例如<?xml version=”1.0”?>。

  2)必须有且只有一个根元素。

  3)标记大小写敏感。

  4)属性值用引号,单引号双引号都可以,但必须一致。

  4)标记成对出现。

  5)空标记必须关闭,可以自关闭。例如:<book/>。

  6)元素正确嵌套,不可以交叉重叠。

  7)名称中可以包含字母数字或其他字符。

  8)名称不能以数字开头。

  9)名称中不能含有空格。

  10)名称中不能包含冒号:(冒号被保留,用作命名空间使用)

 

XML的应用

 

XML独立于计算机平台,操作系统和编程语言来表示数据,凭借其简单,可拓展,交互性和灵活性在计算机行业中得到了管饭的支持和采纳

XML基于文本格式,允许开发人员描述结构化数据并在各种应用之间发送和交换这些数据,使不同系统之间交互数据具备了统一的格式

 

XML应用场景主要体现在一下几点

数据存储:XML与文件,数据库一样,都可以实现数据的持久化存储,XML极其简单,正式这点使XML与众不同

 

数据交换:在实际运用中由于各个计算机所使用的操作系统,数据库不同,因此数据库之间的交换时很复杂的

现在可以使用XML来交换数据,两个不同数据库,都转换为XML文件,以达到交换数据的目的

 

数据配置:许多应用都将配置信息存储在XML文件中

 

解析XML概述

1. DOM(Document Object Model)

 

DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。所以DOM解析器基本原理是把XML文档转化为一个包含其内容的树,并可以对树进行遍历。用DOM解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高,尤其是遇到很大的XML文件的时候。由于它的遍历能力,DOM解析器常用于XML文档需要频繁的改变的服务中。

 

(1)优点:

 

①允许应用程序对数据和结构做出更改。

 

②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。

 

(2)缺点:

 

 ①通常需要加载整个XML文档来构造层次结构,消耗资源大。

 

 

 

2. SAX(Simple API for XML)

 

SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。

 

选择DOM还是选择SAX? 对于需要自己编写代码来处理XML文档的开发人员来说, 选择DOM还是SAX解析模型是一个非常重要的设计决策。 DOM采用建立树形结构的方式访问XML文档,而SAX解析器采用了基于事件的模型,工作原理简单地说就是对文档进行顺序扫描,当扫描到文档开始与结束、元素开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

 

(1)优点:

 

①不需要等待所有数据都被处理,分析就能立即开始。

 

②只在读取数据时检查数据,不需要保存在内存中。

 

③可以在某个条件得到满足时停止解析,不必解析整个文档。

 

④效率和性能较高,能解析大于系统内存的文档。

 

(2)缺点:

 

①需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。

 

②单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。

 

 

 

3. JDOM(Java-based Document Object Model)

 

使用JDOM解析XML需要依赖包jdom.jar,需要下载后导入。

 

JDOM的目的是成为Java特定文档模型,JDOM只是被设计用来处理Java,它简化与XML的交互并且比使用DOM实现更快。JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。并且API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。JDOM它不是一个XML解析器,但是它可以使用SAX,STAX或者DOM解析器用来构建一个JDOM文档。JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)Java/XML问题”。

 

 

 

(1)优点:

 

①使用具体类而不是接口,简化了DOM的API。

 

②大量使用了Java集合类,方便了Java开发人员。

 

(2)缺点:

 

①没有较好的灵活性。

 

②性能较差。

 

 

 

4. DOM4J(Document Object Model for Java)

 

DOM4J在添加灵活性、XPath集成和对大文档处理的目标时,DOM4J的目标与JDOM是一样的:针对Java开发者的易用性和直观操作。它还致力于成为比JDOM更完整的解决方案,实现在本质上处理所有Java/XML问题的目标。在完成该目标时,它比JDOM更少强调防止不正确的应用程序行为。DOM4J是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。实际项目中,往往选择dom4j来解析xml。同样,需要导入http://dom4j.com等。

 

(1)优点:

 

①大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。

 

②支持XPath。

 

③有很好的性能。

 

(2)缺点:

 

①大量使用了接口,API较为复杂。

 

 

使用DOM读取XML数据

 

1. DOM 概念

DOM是Document Object Model的简称,即文档对象模型,DOM 把XML文件映射成一棵倒挂的”树”, 以根元素为根节点,每个节点都以对象形式存在。通过存取这些对象就能够存取XML文档的内容。

book信息的DOM数结构

 

2.使用DOM的步骤

可以使用Onele公司提供的JAXP lJawa API for XML Possn来解析XM. IAXP 包含3个包,

➢org.w3c.dom: W3C推荐的用于使用DOM解析XML文档的接口。

➢org.xml.sax: 用于使用SAX解析XML文档的接口。

➢javax.xml.parsers: 解析器工厂工具,获得并配置特殊的分析器。

在使用DOM解析XML时需要导入这些包中相关的类。JAXP会把XML文档转换成一个DOM树。使用DOM解析XML文档的步骤如下。

(1)创建解析器工厂对象,即DocumentBuilderFactory对象。

(2) 由解析器工厂对象创建解析器对象,即DocumentBuilder对象。

(3) 由解析器对象对指定的XML文件进行解析,构建相应的DOM树,创建Document对象。(4)以Document对象为起点对DOM树的节点进行增加、删除、修改、查询等操作。

 

使用DOM解析XML时主要使用以下对象

 

1) Node对象

Node对象是DOM结构中最基本的对象,代表了文档树中的一个抽象节点。在实际使用的时候,很少会真正用到Node这个对象.一般会用如Document. Element. Text 等Node对象的子对象来操作文档。

Node对象的主要方法如下。

➢getChildNodes( ): 返回包含此节点所有子节点的NodeList。

➢getFirstChild(): 如果节点存在子节点,则返回第一个子节点。

➢getLastChild(): 如果节点存在子节点,则返回最后一一个子节点。

➢getNextSibling(): 返回在DOM树中这个节点的下一个兄弟节点。

➢getPreviousSibling( ):返回在DOM树中这个节点的上一个兄弟节点。

➢getNodeName(): 返回节点的名称。

➢getNodeValue(): 返回节点的值。

➢getNodeType():返回节点的类型。

 

2) NodeList 对象

顾名思义,NodeList 对象是指包含了-一个或多个节点(Node) 的列表。可以简单地把它看成一个Node数组,也可以通过方法来获得列表中的元素。

NodeList对象的常用方法如下

➢getLength(): 返回列表的长度。

➢item(int index):返回指定位置的Node对象。

 

3) Document 对象

Document对象代表整个XML文档,所有其他的Node都以-定的顺序包含在Document对象之内.排列成一个树状结构,可以通过遍历这棵“树” 来得到XML文档的所有内容。它也是对XML文档进行操作的起点,人们总是先通过解析XML源文件而得到一一个Document对象,然后来执行后续的操作。

Document对象的主要方法如下

➢gEiemememeTName(Sring nam) 返回个NoleList对象,它包含了所有给定标签名的。标签。

➢gnDoumemeElemeene ,返回一个代表这个DOM树的根节点的Elemen对象,也就是代表)文档根元素的对象。

 

4) Element 对象

Element对象代表XML文档中的标签元素,继承自Node. 也是Node最主要的子对象。在标签中可以包含属性,因而Element对象中也有存取其属性的方法,如下所示

➢getribrte(Sring atbutename);返回标签中给定属性名称的属性的值。

➢getElementsByTagName(String name):返回具有给定标签名称的所有后代Elements的Nodeis

 

 

使用DOM维护XML数据

 

获取到DOM的数据进行数据的增加,修改,删除后的数据保存到XML文档中

 

使用DOM4J解析XML

 

DOM4J API概述

 

    DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。

    DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。

    Dom:把整个文档作为一个对象。

  DOM4J 最大的特色是使用大量的接口。它的主要接口都在org.dom4j里面定义:

Attribute

定义了 XML 的属性。

Branch

指能够包含子节点的节点。如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为

CDATA

定义了 XML CDATA 区域

CharacterData

是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text.

Comment

定义了 XML 注释的行为

Document

定义了XML 文档

DocumentType

定义 XML DOCTYPE 声明

Element

定义XML 元素

ElementHandler

定义了Element 对象的处理器

ElementPath

被 ElementHandler 使用,用于取得当前正在处理的路径层次信息

Entity

定义 XML entity

Node

为dom4j中所有的XML节点定义了多态行为

NodeFilter

定义了在dom4j 节点中产生的一个滤镜或谓词的行为(predicate)

ProcessingInstruction

定义 XML 处理指令

Text

定义 XML 文本节点

Visitor

用于实现 Visitor模式

XPath

在分析一个字符串后会提供一个 XPath 表达式

 

使用DOM4J操作XML数据

 

要使用DOM4J读写XML文档,需要先下载dom4j的jar包,在https://dom4j.github.io 下载后将相应jar包加入工程就可以使用了。使用DOM4J解析XML的关键操作如下

 

1.Document对象相关

读取XML文件,获取Document对象。

 

SAXReader reader=new SAXReader();

Document document=reader.read( new File(" input.xml "));

 

2.节点相关

(1)获取文档的根元素

 

Element rootElm = document.getRootElement();

 

(2) 取得某节点的单个子节点

 

Element memberElm =rootElm.element(" member");

 

(3) 取得节点的文字

 

String text = memberElm.getText();

 

也可以用

 

String text = rootElm.elementText(" name "); //取得根元素下的name子

节点的文字

 

(4) 取得某节点下名为 “ member ” 的所有子节点并进行遍历

 

List nodes=rootElm.elements(" member ");

for( Iterator it =nodes.iterator(); it.hasNext(); ){

Element elm=( Element ) it.next();

//.......

}

 

(5) 对某节点下的所有子节点进行遍历

for( Iterator it =rootElm.elementItertor; it.hasNext(); ){

Element element=( Element ) it.next();

//.......

}

 

(6) 在某节点下添加子节点。newMemberElm是某个已存在的节点

 

Element ageElm=newMemberElm.addElement(" age");

 

(7) 设置节点文字

 

ageElm.setText(" 29");

 

(8) 删除某节点

parentElm.remove( childElm ); //childElm是待删除的节点,parentElm是某父节点

 

3.属性相关

 

(1)取得某节点的某属性

 

Element root=document.getRootElement();

Attribute attribute=root.attribute(" size"); //属性名 size

(2) 取得属性值

 

String text = attribute.getText();

 

也可以用:

 

// 取得根节点下name子节点的firstname属性值

String text2=root.element(" name").attributeValue(" firstname ");

 

(3) 遍历某节点的所有属性

 

Element root=document.getRootElement();

 

for(Iterator attribute=(Attribute) it.next){

Attribute attribute =(Attribute) it.next();

String text=attribute.getText();

System.out.println(text);

}

 

(4) 为某节点添加属性

 

newMemberElm.addAttribute(" name"," learningdom4j");

 

(5) 设置属性的值

 

Attribute attribute =root.attribute(" name");

attribute.setText(" learningdom4j");

 

(6) 删除某属性

 

Attribute attribute =root.attribute(" size") ;

root.remove(attribute );

 

 

 

4.将文档写入XML文件

 

(1) 文档中全为英文,不设置编码格式,直接写入

 

XMLWriter writer=new XMLWriter( new FileWriter (" output.xml "));

writer .write(document);

writer.class();

 

(2) 文档中含有中文,设置编码格式再写入。

 

OutputFormat format=OutputFormat .createPrettyPrint();

format.setEncoding(" GBK "); // 指定XML编码

XMLWriter writer=new XMLWriter( new FileWriter (" output.xml "),

format );

writer .write(document);

writer.class();

 

例如:使用DOM4J读取收藏信息。 关键步骤

 

1. 导入dom4j的jar包。

2. 指定要解析的XML文件

3. 把XML文件转换成Document对象

4. 获取节点属性或文本的值。

 

 

XML 使用的代码

第一步

<?xml version="1.0" encoding="UTF-8" ?>

<size>

<S height="height&lt;165"></S>

<M height="height&lt;165"></M>

</size>

 

第二步

package cn.bosp;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

 

public class Demol {

public static void main(String[] args)throws Exception {

//使用DOM读取xml文件的信息到 document对象中

DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();

DocumentBuilder documentBuilder=dbf.newDocumentBuilder();

Document document=documentBuilder.parse("src/size.xml");

//获得根节点(size)

NodeList nodeList=document.getElementsByTagName("size");

Node sizeNode=nodeList.item(0);

//获得根节点下的子节点

NodeList nodeList1=sizeNode.getChildNodes();

for (int i=0;i<nodeList1.getLength();i++){

Node temp=nodeList1.item(i);

if (temp.getNodeType()==Node.ELEMENT_NODE){

Element element=(Element)temp;//得到S M 元素

String value=element.getAttribute("height");

String elementName=element.getTagName();//元素的名字

System.out.println(elementName);

System.out.println("height="+value);

}

}

}

}

 

 

XML里面的 增,删,改,查

 

增加:

 

package cn.bosp;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import java.io.File;

 

public class Demo7 {

public static void main(String[] args) {

try {

// 增加

DocumentBuilderFactory documentBuilderFactory=

DocumentBuilderFactory.newInstance();

DocumentBuilder documentBuilder=

documentBuilderFactory.newDocumentBuilder();

Document document=((DocumentBuilder) documentBuilder).parse("src/size.xml");

Node studentNodeList=document.getElementsByTagName("students").item(0);

Element studentElement=document.createElement("student");

studentElement.setAttribute("name","刘德华");

studentNodeList.appendChild(studentElement);

Element addressElement=

document.createElement("address");

addressElement.setTextContent("大白兔");

studentElement.appendChild(addressElement);

 

TransformerFactory transformerFactory=

TransformerFactory.newInstance();

Transformer transformer=

transformerFactory.newTransformer();

DOMSource domSource=new DOMSource(document);

StreamResult streamResult=new

StreamResult(new File("src/size.xml"));

transformer.setOutputProperty("encoding","UTF-8");

transformer.transform(domSource,streamResult);

}catch (Exception e){

e.printStackTrace();

}

}

}

 

修改:

 

package cn.bosp;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import java.io.FileOutputStream;

 

public class Demo9 {

public static void main(String[] args) {

try {

//修改

DocumentBuilderFactory documentBuilderFactory=

DocumentBuilderFactory.newInstance();

DocumentBuilder documentBuilder=

documentBuilderFactory.newDocumentBuilder();

Document document=documentBuilder.parse("src/size.xml");

 

NodeList nodeList=document.getElementsByTagName("student");

for (int i=0;i<nodeList.getLength();i++){

Element element=(Element)nodeList.item(i);

String value=element.getAttribute("name");

 

if (value.equals("赵四")){

element.setAttribute("naem","万代");

}

}

TransformerFactory transformerFactory=

TransformerFactory.newInstance();

Transformer transformer=transformerFactory.newTransformer();

DOMSource domSource=new DOMSource(document);

StreamResult streamResult=new StreamResult(new

FileOutputStream("src/size.xml"));

 

transformer.setOutputProperty("encoding","UTF-8");

transformer.transform(domSource,streamResult);

}catch (Exception e){

e.printStackTrace();

}

}

}

 

刪除:

 

package cn.bosp;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import java.io.File;

 

public class Demo6 {

public static void main(String[] args){

try {

//删除

DocumentBuilderFactory documentBuilderFactory=

DocumentBuilderFactory.newInstance();

DocumentBuilder documentBuilder=documentBuilderFactory

.newDocumentBuilder();

Document document=documentBuilder.parse("src/size.xml");

Node studentNode=document.getElementsByTagName("students").item(0);

NodeList studentNodeList=document.getElementsByTagName("student");

Element studentElement=null;

for (int i=0;i<studentNodeList.getLength();i++){

studentElement=(Element)studentNodeList.item(i);

if (studentElement.getAttribute("name").equals("老七")){

break;

}

}

if (studentElement!=null){

studentNode.removeChild(studentElement);

}

TransformerFactory transformerFactory= TransformerFactory.newInstance();

Transformer transformer=transformerFactory.newTransformer();

DOMSource domSource=new DOMSource(document);

StreamResult streamResult=new StreamResult(new File("src/size.xml"));

transformer.setOutputProperty("encoding","UTF-8");

transformer.transform(domSource,streamResult);

}catch (Exception e){

e.printStackTrace();

}

}

}

 

查询:

package cn.bosp;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

 

public class Demo8 {

public static void main(String[] args) {

try{

// 展示并且打印

DocumentBuilderFactory documentBuilderFactory=

DocumentBuilderFactory.newInstance();

DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();

Document document= documentBuilder.parse("src/size.xml");

 

Node nodeList =document.getElementsByTagName("students").item(0);

NodeList childNodesList=nodeList.getChildNodes();

 

for (int i=0;i<childNodesList.getLength();i++){

Node childNode=childNodesList.item(i);

if (childNode.getNodeType()==Node.ELEMENT_NODE){

Element brandElement=(Element)childNode;

String brandElementAttribute=brandElement.getAttribute("name");

System.out.println("学生名字:"+brandElementAttribute);

 

NodeList addressNodeList=brandElement.getChildNodes();

for (int j=0;j<addressNodeList.getLength();j++){

Node addressNode=addressNodeList.item(j);

if (addressNode.getNodeType()==Node.ELEMENT_NODE){

Element addressNodeElement=(Element)addressNode;

String address=addressNodeElement.getTextContent();

System.out.println("学生地址:"+address);

System.out.println("---------");

}

}

}

}

}catch (Exception e){

e.printStackTrace();

}

}

}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值