用DOM/JDOM解析XML文件

JDOM实现XML文件的遍历 前言:DOM和SAX是跨语言的XML的解析准备,在Java 中使用却没有那么方便。Java 拥有自己的JDOM 和DOM4J(DOM for Java),这两个是专门为Java语言提供的解析工具,使用起来很方便,本文首先来介绍一下运用JDOM下的DOM和SAX分别来实现对XML文件元素的遍历。 1、使用DOM方式。   (1)首先我们有一个XML文件,存储student 元素: 阅读详情

   夜已经深了,可是我仍未眠。明天就要回家过年了,对于一个飘荡在外的游子来说,回家过年是一件多么激动人心的事啊!这才是我心中真正的年啊!
   真希望新的一年快点到来,因为有太多的不愉快需要忘记、因为有太多的梦想需要去实现……

   前一段时间要解析一个XML文件,就是对XML进行增、删、改的操作。以前做J2EE时一直都是用第三方的类库来辅助解决的,但这次却要求自己用DOM来解析,只能用JDK自带的类库!
   一直到现在还没有想通:为什么要重复发明轮子呢???但是事情还是要做的,我只是俗人,我也要吃饭……
   又或许,这只是我的又一个自我解嘲的借口罢了!

  下边的类其实有很多不足的地方的,但我却始终不能说服我自己, 我就是这样一个倔强又刚愎自用的人,期待来年吧,希望走过本命年的我能成熟起来,对于一些事情的控制更自由一些。。。

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.StringTokenizer;

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 org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* <p>ConfigParser</p>
* 1. read the config XML,or update the file.</br>
* 2. query a property from the config file,the property name fromat:A.B.C etc.</br>
* 3. add properties into the config file.</br>
*
* <p>@author javer QQ:84831612</p>
*/
public class ConfigParser
{
   private File xmlFile = null;

   private Document doc = null;

   private Element root = null;

   public ConfigParser(String filename)
   {
      xmlFile = new File(filename);
      try
      {
         DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
         doc = builder.parse(xmlFile);
         root = doc.getDocumentElement();
       }
       catch(Exception e)
       {
          System.err.println("Error creating XML parser in ConfigParser.java");
          e.printStackTrace();
       }
   }

   /**
   * Return the value of the specified property.
   *
   * @param name the name of the property to get.
   * @return the value of the specified property.
   */
   public String getValue(String name)
   {
      String[] propName = parsePropertyName(name);
   
      NodeList nodes = root.getElementsByTagName(propName[0]);
      if(nodes == null || nodes.getLength() < 1)
         return null;
      for(int i = 1; i < propName.length; i++)
      {
         nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]);
         if(nodes == null || nodes.getLength() < 1)
            return null;
      }
   
      Node node = nodes.item(0).getChildNodes().item(0);
      if(node != null)
         return node.getNodeValue();
      else
         return null;
   }
   
   /**
   * <p>Add the values by the specified properties.</p>
   * For example:</br>
   * if values is existed as follow</br>
   * x.y.z1=1</br>
   *    .z2=2</br>
   *    .z3=3</br>
   * and now, you need add new values as a new group,like as follow values</br>
   * x.y.z1=11</br>
   *    .z2=22</br>
   *    .z3=33</br>
   * you need call this function like as follow:</br>
   * addValue("x.y",new String[]{"z1","z2","z3"},new String[]{"11","22","33"})</br>
   * and the XML will have a result as follow:</br>
   * <xml>
   *    <x>
   *       <y>
   *          <z1>1</z1>
   *          <z2>2</z2>
   *          <z2>3</z2>
   *       </y>
   *       <y>
   *          <z1>11</z1>
   *          <z2>22</z2>
   *          <z2>33</z2>
   *       </y>
   *    </x>
   * </xml>
   *
   * @param parentName
   * @param subNames
   * @param values
   */
   public void addValue(String parentName, String[] subNames, String[] values)
   {
      String[] propName = parsePropertyName(parentName);

      NodeList nodes = root.getElementsByTagName(propName[0]);
      if(nodes == null || nodes.getLength() < 1)
      {
        root.appendChild(doc.createElement(propName[0]));
        nodes = root.getElementsByTagName(propName[0]);
      }
      Element tempElement = ((Element)nodes.item(0));
      for(int i = 1; i < propName.length - 1; i++)
      {
         tempElement = ((Element)nodes.item(0));
         nodes = tempElement.getElementsByTagName(propName[i]);
         if(nodes == null || nodes.getLength() < 1)
         {
            tempElement.appendChild(doc.createElement(propName[i]));
            nodes = tempElement.getElementsByTagName(propName[i]);
         }
      }

      tempElement = (Element)tempElement.appendChild(doc.createElement(propName[propName.length - 1]));
      Node node = null;
      for(int i = 0; i < subNames.length; i++)
      {
         node = tempElement.appendChild(doc.createElement(subNames[i]));
         node.appendChild(doc.createTextNode(values[i]));
      }

      store();
   }

   /**
   * Update the value of the specified property.
   * @param name
   * @param value
   */
   public void updateValue(String name, String value)
   {
      String[] propName = parsePropertyName(name);

      NodeList nodes = root.getElementsByTagName(propName[0]);
      if(nodes == null || nodes.getLength() < 1)
         return;
      for(int i = 1; i < propName.length; i++)
      {
         nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]);
         if(nodes == null || nodes.getLength() < 1)
            return;
      }

      Node node = nodes.item(0).getChildNodes().item(0);
      if(node != null)
         node.setNodeValue(value);
      else
         return;

      store();
   }

   /**
   * Deletes the specified property.
   *
   * @param name the property to delete.
   */
   public void deleteProperty(String name)
   {
      String[] propName = parsePropertyName(name);
      if(propName.length == 1)
         root.removeChild(root.getElementsByTagName(propName[0]).item(0));
      else
      {
         NodeList nodes = root.getElementsByTagName(propName[0]);
         for(int i = 1; i < propName.length - 1; i++)
         {
            nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]);
            if(nodes == null || nodes.getLength() < 1)
               return;
         }

         nodes.item(0).removeChild(((Element)nodes.item(0)).getElementsByTagName(
         propName[propName.length - 1]).item(0));
      }

      store();
   }

   /**
   * Return all children property names of a parent property as a String array,
   * or an empty array if the if there are no children. For example, given
   * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then
   * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
   * <tt>C</tt>.
   *
   * @param parent the name of the parent property.
   * @return all child property values for the given parent.
   */
   public String[] getChildrenProperties(String parent)
   {
      String[] propName = parsePropertyName(parent);
      NodeList nodes = root.getElementsByTagName(propName[0]);
      if(nodes == null || nodes.getLength() < 1)
         return null;
      for(int i = 1; i < propName.length; i++)
      {
         nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]);
         if(nodes == null || nodes.getLength() < 1)
            return null;
      }

      nodes = nodes.item(0).getChildNodes();
      ArrayList list = new ArrayList();
      for(int i = 0; i < nodes.getLength(); i++)
      {
         if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE)
            list.add(nodes.item(i).getNodeName());
      }

      if(list == null)
         return null;
      else
         return (String[])list.toArray(new String[list.size()]);
   }

   /**
   * Return the value when the specified property key and value is existent,
   * and return null if the specified property key and value is not existent
   *
   * @param name
   * @param value
   * @return
   */
   public String findValue(String name, String value)
   {
      String[] propName = parsePropertyName(name);
      return findValue(root, 0, propName, value);
   }

   private String findValue(Element element, int depth, String[] propName,String value)
   {
      String _value = null;
      if(depth == propName.length)
      {
         _value = element.getChildNodes().item(0).getNodeValue();
         if(_value.equals(value))
            return value;
         else
            return null;
      }

      NodeList children = element.getElementsByTagName(propName[depth]);
      if(children == null || children.getLength() < 1)
         return null;
      else
         ++depth;

      for(int i = 0; i < children.getLength(); i++)
      {
         if(children.item(i).getNodeType() != Node.ELEMENT_NODE)
            continue;

         element = (Element)children.item(i);
         _value = findValue(element, depth, propName, value);
         if(_value != null)
         {
            return value;
         }
      }

      return null;
   }

// public static void main(String[] args) throws Exception
// {
// System.out.println("Start****************************");
// ConfigParser test = new
// ConfigParser("/test.xml");

// update
// System.out.println(test.getValue("x.y"));
// test.updateValue("x.y","xyz");
// System.out.println(test.getValue("x.y"));

// delete
// System.out.println(test.getValue("x.y"));
// test.deleteProperty("x.y");
// System.out.println(test.getValue("x.y"));

// getChildrenProperties
// String[] childrenNames = test.getChildrenProperties("x.y");
// if(childrenNames!=null)
// for(int i=0;i<childrenNames.length;i++)
// {
// System.out.println("childrenNames["+i+"]=" + childrenNames[i]);
// }

// find
// System.out.println(test.findValue("x.y.z1","cc22"));

// add
// test.addValue("x.y",new String[]{"z1","z2","z3","z4"},new String[]{"11","22","33","44"}
// );
//
// System.out.println("End****************************");
// }

   private synchronized void store()
   {
      boolean error = false;
      File tempFile = new File(xmlFile.getParentFile(), xmlFile.getName() + ".tmp");
      FileOutputStream out = null;
      try
      {
         DOMSource ds = new DOMSource(root);
         out = new FileOutputStream(tempFile);
         StreamResult sr = new StreamResult(out);
         TransformerFactory tff = TransformerFactory.newInstance();
         Transformer tf = tff.newTransformer();
         tf.transform(ds, sr);
      }
      catch(Exception e)
      {
         e.printStackTrace();
         error = true;
      }
      finally
      {
         try
         {
            out.flush();
            out.close();
         }
         catch(Exception e)
         {
            e.printStackTrace();
            error = true;
         }
      }

      if(!error)
      {
         xmlFile.delete();
         tempFile.renameTo(xmlFile);
      }
   }

   private String[] parsePropertyName(String name)
   {
      int size = 1;
      for(int i = 0; i < name.length(); i++)
      {
         if(name.charAt(i) == '.')
         {
            size++;
         }
      }
      String[] propName = new String[size];
      StringTokenizer tokenizer = new StringTokenizer(name, ".");
      int i = 0;
      while(tokenizer.hasMoreTokens())
      {
         propName[i] = tokenizer.nextToken();
         i++;
      }
      return propName;
   }
}

   既然提到了JDOM,就不得不搞清楚它和DOM的关系,免得被人问及为何选择此种解决方案时再次无言 ;) (具体的理论性质的比较,google、baidu上有一堆堆的说明,这里就不再copy)同样的类,还有一个用JDOM的实现版本,同样多的代码量下,JDOM的容错性、可扩展性似乎更好些。这一页的内容太多,还是放到下一页吧……

掌握Java DOM与JDOM的XML处理技术 本文还有配套的精品资源,点击获取 简介:Java DOM和JDOM是处理XML文档的两种核心库,都基于W3C的DOM规范。DOM是一个跨平台的标准API,而JDOM是专为Java优化的DOM实现,提供了更直观的API和性能优化。了解两者的不同,有助于在实际项目中根据需求选择合适的XML处理方法。 1. DOM和JDOM基础介绍 在当今的IT领域中,XML作为... 阅读详情

相关推荐

Vue 10分钟入门VR全景显示 基于photo-sphere-viewer

文章目录前言一、引入photo-sphere-viewer?二、使用步骤1.引入库2.声明容器3.内容加载4.全部代码总结 前言 由于工作的需求,要实现全景图片的展示与预览,本来以为会是一个很难的内容,没想到使用现成的组件photo-sphere-viewer就可以轻松实现,上手只需要10分钟! 一、引入photo-sphere-viewer? 可以直接通过npm进行引入 npm install photo-sphere-viewer 二、使用步骤 1.引入库 photo-sphere-viewer

YIGE_MO的博客 5866

用DOM/JDOM解析XML文件(3)

  几乎就要放弃了,但还是忘不了,终于还是又登录了。  每当夜深人静的时候,每当独孤无助的时候,每当满腹心事的时候,除了我的blog,还有谁,愿意听我的倾诉呢?  还是那句话:夜未眠,我的blog陪我未眠,我未眠,我陪我的blog未眠……  以前记录过两个自己写的读写XML文件的帖子,感觉很不完善,只适合简单的应用,无法完成更复杂高级的功能。最近正好用到一个更优雅的,再记录下来,以备以后查阅。

3977

GDI文字绘制和windows下opengl文字绘制小结

GDI绘制文字,要设置文字的属性,主要就是通过设置DC中的font对象来实现的。 font对象的创建可以由createfont()、createfontIndirect()来实现。 HFONT CreateFont( int nHeight, // height of font int nWidth, // average

T_W_S的专栏 5323

用DOM/JDOM解析XML文件(2)

      很久没有发贴了,似乎已经彻底遗忘了这个角落。也许,只有在心情低落的时候才会想起,只有我的blog能陪我彻夜无眠。就像一只受伤的动物,总有一个秘密的藏身之处,与世隔绝,只有自己知道,在这个私人的角落,有梦想、有回忆、有失落、也有甜蜜……       上次的文章末尾提到要补一个同样功能的JDom版XML解析器,找了半天,似乎丢了,勉强看到一个,也不知道是不是当时的最终版本,乍一看上去,

2181

基于 openEuler 24.03 LTS 源码编译安装 Zabbix 7.4

Zabbix是一款开源的企业级分布式监控系统,支持网络、服务器、应用等多种IT资源的监控。核心功能包括数据采集、告警通知、可视化展示等,采用Server/Agent架构,支持多种操作系统。本文详细介绍了在openEuler 24.03系统上部署Zabbix 7.4.2的完整流程,包括环境准备、MySQL配置、PHP/Apache安装、Zabbix编译安装等步骤,为构建企业级监控系统提供了实践指导。

广然笔记 1191

通信模组性能调优

本文介绍了高通平台通信模组性能调优的方法,主要包括硬件加速技术和CPU负载优化。针对CPU负载优化,提出了内核RPS/RFS功能启用、网卡队列调整、中断均衡、CPU性能模式设置等措施。同时建议关闭热管理并加强散热,调整TCP接收/发送缓存大小以解决TCP异常报文问题。这些优化手段可显著提高整机吞吐率测试中的网络性能表现。

四儿家的小祖宗的博客 1359

三类XML文件的解析方法

XML文件的解析 mybatis的学习当中,配置的加载传统的是通过解析用户配置的文件,获取到数据库连接与对象实体映射关系的,书中有描述到DOM\SAX\StAX 几种方案,一方面是夯实基础,一方面是了解三种方法的优缺点,今天就学习一下XML文件的解析 一、XML的解析方式 DOM 解析XML底层接口之一,跨平台,跨语言 SAX 解析XML底层接口之一 Jdom/dom4J 基于底层API的封装,Java语言,更方便便捷 二、DOM解析 DOM 解析的原理:树形结构,依赖内存加载文件,树在内存中

c_zyer的博客 705

Google Earth Engine(GEE)——将sentinel - 2影像所有波段重采样到10m分辨率 (resample 和 projection的使用)

影像重投影是将一个影像从一个坐标系投影到另一个坐标系的过程。这通常涉及到将像素从一个平面坐标系变换到另一个平面坐标系。这可以用于许多应用中,例如建立数字高程模型(DEM)和地图制图。影像重投影通常需要进行数学计算,包括转换矩阵和插值算法,以确保像素值的准确性和精度。这次我们将对哨兵2好数据中20m分辨率的波段,重采样到10m分辨率中,然后同一参与计算。

此星光明博客 3108

问题:XML数据进行解析的方式有哪些呢?

上回我们说到 JSON 解析的四种方式,那么这次我们来看看 XML 的四种解析方式。 解析的四种方式 DOM 解析 SAX 解析 JDOM 解析 DOM4J 解析 案例实操 DOM 解析 DOM(Document Object Model, 文档对象模型),在应用程序中,基于 DOM 的 XML 分析器将一个 XML 文档转换成一个对象模型的集合(通常称为 DOM 树),应用程序正是通过对这个对象模型的操作,来实现对 XML 文档数据的操作。XML 本身是以树状的形式出现的,所以 DOM 操作的时候,也

weixin_53374029的博客 91

18006.STM32通过SPI读取LAN9253数据

【代码】18006.STM32通过SPI读取LAN9253数据。

写给自己的笔记 556

教你如何阅读Autosar代码(6):常量变量定义

编译器抽象应该为常量的声明和定义定义CONST宏。编译器抽象应该定义VAR宏来声明和定义变量。memclass:常量本身的分类;memclass:变量本身的分类;vartype:变量的类型;type:常量的类型;

wdconan001的博客 958

web开发总结----xml的写入、读取---1

两种解析方式:  DOM(Document Object Model 文档对象模型)  关键字:树(Document)  优点: 把 xml 文件在内存中构造树形结构,可以遍历和修改节点  缺点: 如果文件比较大,内存有压力,解析的时间会比较长  SAX(Simple API for Xml 基于 XML 的简单 API)  关键字:流(Stream)  把 xml 文件作为输入...

iteye_8039的博客 242

OpenGL 进阶系列10 - 光线跟踪实现简介(Ray Tracing)

OpenGL 实现光线跟踪(Ray Tracing)是一个相对复杂但有趣的挑战,通常用于生成高度逼真的图像效果,如反射、折射、阴影等。OpenGL 本身并不是为光线跟踪设计的,但可以通过结合计算着色器和现代 OpenGL 功能实现光线跟踪。光线跟踪的基本思路是从相机(或视点)出发,发射光线并计算这些光线与场景中物体的交点。光线与场景中物体相交的计算。计算交点的光照(基于表面法线、光源位置、材质等)。反射和折射的处理(如果物体是透明或反射的)。

GPU全栈博主 1534

Java中Dom解析XML

DOM将整个XML文件加载到内存中,并构建出节点树;应用程序可以通过遍历节点树的方式来解析XML文件中的各个节点、属性等信息;这种方式便于对XML节点的添加修改等,而且解析也很方便,然后它比较耗费内存,解析速度也不快 sax解析: http://www.cnblogs.com/gavinYang/p/3505543.html dom4j解析: http://www.cnblogs.com/ga...

brywzy的博客 53

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

XML解析技术

 XML学习完了,老师说在面试的时候有可能要问到这些,所以又找了些资料,在MLDN的这段日子里,老师们都把各个面试中有可能要问到的问题都帮我们一一总结,真的很感谢MLDN的全部老师,项目老师帮我们认真的讲解项目,辅导项目,教学老师帮我们认真总结各个技术,感谢,真的是感谢,呵呵,我会努力搞好的 Java中四种XML解析技术  在平时工作中,难免会遇到把 XML 作为数据存储格式。面对目前种类繁多的解

vteiawypm的专栏 563

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Java中四种XML解析技术

在平时工作中,难免会遇到把 XML 作为数据存储格式。面对目前种类繁多的解决方案,哪个最适合我们呢?在这篇文章中,我对这四种主流方案做一个不完全评测,仅仅针对遍历 XML 这块来测试,因为遍历 XML 是工作中使用最多的(至少我认为)。   预 备   测试环境:   AMD 毒龙1.4G OC 1.5G、256M DDR333、Windows2000 Server SP4、Sun...

zhglhy的专栏 131

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

XML 手册解析为 HTML 的流程与实现

摘要:本文介绍了将XML手册转换为HTML文档的完整流程。首先解析XML文件(使用DOM或SAX),提取标签、属性和文本内容;然后映射到HTML元素,通过StringBuilder拼接或模板引擎生成HTML;最后输出为.html文件。提供了Java代码示例(DOM解析+手动生成HTML),并建议使用XSLT转换处理复杂XML结构。该方案可实现结构化数据到可视化网页的转换,支持扩展CSS样式美化输出效果。

m0_73874622的博客 210

Jdom解析多层xml文件

Jdom解析多层xml文件 一、Jdom简介: JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。     JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。 在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档

md_shmily92的专栏 1724

DOM、JDOM、DOM4J解析XML

DOM、JDOM、DOM4J解析XML JAVA解析XML通常有两种方式,DOM和SAX(SAX前面已经示范) DOM:Document Object Model(文档对象模型) DOM的特性: 定义一组JAVA接口,基于对象,与语言和平台无关将XML文档表示为树,在内存中解析和存储XML文档,允许随机访问文档的不同部分 DOM解析XML DOM的优点,由于树在内存中是持久的,因此可以修改后更新,它还可以在任何时候在树中上下导航,API使用起来也比较简单。 解析步骤: DocumentBuilderFact

七一 1043

对XML文件的解析,DOM、SAX、JDOM、JAXB还有dom4

1.  DOM(Document Object Model)   此 方法主要由W3C提供,它将xml文件全部读入内存中,然后将各个元素组成一棵数据树,以便快速的访问各个节点 。 因此非常消耗系统性能 ,对比较大的文档不适宜采用DOM方法来解析。 DOM API 直接沿袭了 XML 规范。每个结点都可以扩展的基于 Node 的接口,就多态性的观点来讲,它是优秀的,但是在 Java 语言中的应用不

hexi_sijin的专栏 1711

Java解析XML汇总(DOM/SAX/JDOM/DOM4j/XPath)

【目录】 一、【基础知识——扫盲】 二、【DOM、SAX、JDOM、DOM4j简单使用介绍】 三、【性能测试】 四、【对比】 五、【小插曲XPath】 六、【补充】 关键字:Java解析xml、解析xml四种方法、DOM、SAX、JDOM、DOM4j、XPath 【引言】 目前在Java中用于解析XML的技术很多,主流的有DOM、SAX、JDOM、DOM4j,下文主要介绍

SMCwwh 8万+

DOM、JDOM、DOM4J解析XML实例

一、DOM方式 原始name.xml 李华 14 张三 16 王娟 18 数据模型Student.java package com.upcgrid.dom; public class Student { private String name; private String sex; pri

shijinupc的专栏 1620

DOM、JDOM、DOM4J的区别

随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666) dom是解析xml的底层接口之一(另一种是sax) 而jdom和dom4j则是基于底层api的更高级封装 dom是通用的,而jdom和dom4j则是面向java语言的 DOM 是用与平台和语言无关的方式表示 XM...

孤云博客 2292
上一篇: 用java取得linux系统cpu、内存的实时信息
下一篇: 用DOM/JDOM解析XML文件(2)
java008
博客等级 码龄23年 6粉丝 31原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值