XPath and Default Namespace handling

转自 http://wakan.blog.51cto.com/blog/59583/7220

原文 http://www.edankert.com/defaultnamespaces.html

 

 

诸如“为什么用 XPath 的表达式进行查询,却没有返回所期望的结果?” 的问题通常都与命名空间(NameSpace)有关,而且绝大多数是与缺省命名空间(Default Namespace)有关。本文试图解释这个问题并针对三种流行的 XPath 实现给出解决方法:Jaxen、JAXP XPPathFactory 以及 XSLT。

内容列表

  • 问题描述
  • “前缀-命名空间”映射
  • Jaxen 和 Dom4J
  • Jaxen 和 XOM
  • Jaxen 和 JDOM
  • JAXP XPathFactory
  • XSLT
  • 结束语
  • 资源

问题描述

看下述 XML:
<catalog>
  <cd>
    <artist>Sufjan Stevens</artist>
    <title>Illinois</title>
  </cd>
  <cd>
    <artist>Stoat</artist>
    <title>Future come and get me</title>
  </cd>
  <cd>
    <artist>The White Stripes</artist>
    <title>Get behind me satan</title>
  </cd>
</catalog>
    你可以使用“//cd”来得到没有在任何命名空间中定义的“cd”节点。 
    现在让我们来改造这个 XML,让它的所有元素都属于 'http://www.edankert.com/examples/' 命名空间中。
 
    为了避免在每个不同的元素前都要加个前缀,我们在根元素上定义通常所说的缺省命名空间。改造后的 XML 如下:
 
<catalog xmlns="http://www.edankert.com/examples/">
  <cd>
    <artist>Sufjan Stevens</artist>
    <title>Illinois</title>
  </cd>
  <cd>
    <artist>Stoat</artist>
    <title>Future come and get me</title>
  </cd>
  <cd>
    <artist>The White Stripes</artist>
    <title>Get behind me satan</title>
  </cd>
</catalog>
    当我们使用与上文相同的 XPath “//cd”,将得不到任何元素。这是因为指定的 XPath 返回的是所有 不属于任何命名空间的“cd”节点,而本例中,所有的“cd”元素都属于缺省的命名空间“ [url]http://www.edankert.com/examples/[/url]”。

“前缀-命名空间”映射

    为了取出命名空间“ [url]http://www.edankert.com/examples/[/url]”中的所有“cd”元素,我们需要对 XPath 表达式做一些额外的工作。
 
    为了解决这个问题,XPath 规范允许我们使用 QName 来指定元素或者属性。QName 可以是元素的直接名称(形如“element”),或者包含一个前缀(形如“pre:element”)。这个前缀需要映射到一个命名空间的 URI 上。例如,如果把“pre”前缀映射到“ [url]http://www.edankert.com/test[/url]”上,则通过“pre:element”可以查找出属于命名空间“ [url]http://www.edankert.com/test[/url]”的所有 “element”元素。
 
    在本例中,我们把“edx”映射到“ 'http://www.edankert.com/examples/”命名空间上。通过 XPath“//edx:cd”就可以查找出属于“ 'http://www.edankert.com/examples/”命名空间的所有“cd”元素。 
 
    XPath 处理器允许设置“前缀-命名空间”的映射,但是,如何去映射,却要依赖于具体的实现。下文举例说明 Jaxen (JDOM/dom4j/XOM)、JAXP 以及 XSLT 中是如何进行“前缀-命名空间”的映射的。

Jaxen 和 Dom4J

    下述代码从文件系统读入一个 XML 文件到 org.dom4j.Document 对象中,并且在 Document 中查找属于“ [url]http://www.edankert.com/examples/[/url]”命名空间的所有“cd”元素。
 
try {
 
SAXReader reader = new SAXReader();
  Document document = reader.read( "file:catalog.xml");
 
 
HashMap map = new HashMap ();
  map.put( "edx", "http://www.edankert.com/examples/");
 
  XPath xpath = new Dom4jXPath( "//edx:cd");
  xpath.setNamespaceContext( new
SimpleNamespaceContext ( map));
 
 
List nodes = xpath.selectNodes( document);
 
  ...
 
} catch (
JaxenException e) { // An error occurred parsing or executing the XPath ... } catch ( DocumentException e) {
  // the document is not well-formed.
  ...
}
    第一步,创建一个 SAXReader,用来从文件系统中读取“catalog.xml”并创建一个特定于 Dom4j 的 Document 对象。
    第二步,对于所有 Jaxen 实现都一样,就是创建一个 HashMap 对象,用于保存“前缀-命名空间的 URI”的映射。
 
    为了能通过 Dom4j 使用 Jaxen 的 XPath 功能,需要创建一个与 Dom4j 相关的 XPath 对象:Dom4jXPath。创建方法是把 XPath 的表达式(即“//edx:cd”)传给 Dom4jXPath 的构造方法。
 
    现在,我们已经创建了 XPath 对象,接下来可以把“前缀-命名空间”的映射表传递给 XPath 引擎:把这个 HashMap 映射表用 SimpleNamespaceContext 包装起来。SimpleNamespaceContext 是 Jaxen 的 NamespaceContext 接口的默认实现类。
 
    最后一步就是调用 XPath 对象的 selectNodes() 方法进行查找。并把完整的 Dom4j  Document 对象作为参数传递进去。实际上,Document 中的任何结点都可以作为参数。

Jaxen 和 XOM

    XOM 是基于简单的 Java DOM APIs 之上的最新工具,它的设计初衷是提供简单和易学易用的接口。
 
try {
 
Builder builder = new Builder();
  Document document = builder.build( "file:catalog.xml");
 
 
HashMap map = new HashMap ();
  map.put( "edx", "http://www.edankert.com/examples/");
 
  XPath xpath = new XOMXPath( "//edx:cd");
  xpath.setNamespaceContext( new
SimpleNamespaceContext ( map));
 
 
List nodes = xpath.selectNodes( document);
 
  ...
 
} catch (
JaxenException e) { // An error occurred parsing or executing the XPath ... } catch ( IOException e) {
  // An error occurred opening the document
  ...
} catch ( ParsingException e) {
  // An error occurred parsing the document
  ...
}
 
    我们需要创建一个 Builder 对象,从文件系统中读取“ catalog.xml”文件,并创建出与 XOM 相关的 Document 对象。
 
    下一步创建出包含了“前缀-命名空间”映射关系的 HashMap 对象。
 
    我们需要创建一个特定于 XOM 的 XPath 对象: XOMXPath。创建方法是把 XPath 表达式传递给构造方法,然后就可以通过 XOM 使用 Jaxen 的 XPath 功能了。
 
    创建完 XPath 对象后,同样,我们把“前缀-命名空间”的映射表用 SimpleNamespaceContext 对象封装后,传递给 XPath 引擎。
 
    最后调用 XPath 对象的“selectNodes()”方法进行查找,把 XOM Document 对象作为本方法的参数。

Jaxen 和 JDOM

    JDOM 是第一个提供简单的 XML 访问 API 的工具。 
 
try {
 
SAXBuilder builder = new SAXBuilder();
  Document document = builder.build( "file:catalog.xml");
 
 
HashMap map = new HashMap ();
  map.put( "edx", "http://www.edankert.com/examples/");
 
  XPath xpath = new JDOMXPath( "//edx:cd");
  xpath.setNamespaceContext( new
SimpleNamespaceContext ( map));
 
 
List nodes = xpath.selectNodes( document);
 
  ...
 
} catch (
JaxenException e) { // An error occurred parsing or executing the XPath ... } catch ( IOException e) {
  // An error occurred opening the document
  ...
} catch ( JDOMException e) {
  // An error occurred parsing the document
  ...
}
 
    首先,通过 SAXBuilder 创建了一个特定于 JDom 的 Document 对象。
 
    接着创建一个特定于 JDOM 的 XPath 对象: JDOMXPath。
 
    然后,把“前缀-命名空间”的映射表(HashMap)用 SimpleNamespaceContext 对象封装起来,传递给 XPath 引擎。
 
    最后调用 XPath 对象的“selectNodes()”方法来进行查找,并把 JDOM 的 Document 对象作为本方法的输入参数。

JAXP XPathFactory

    从 1.3 版起, JAXP 还提供了一种在 XML Object Models 上进行查询的通用机制。 
 
try {
 
DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance();
  domFactory.setNamespaceAware( true);
 
 
DocumentBuilder builder = domFactory.newDocumentBuilder(); Document document = builder.parse( new InputSource ( "file:catalog.xml"));
 
 
XPathFactory factory = XPathFactory .newInstance();
 
XPath xpath = factory.newXPath();
  xpath.setNamespaceContext( new
NamespaceContext () {
    public
String getNamespaceURI( String prefix) {
      if ( prefix.equals( "edx")) {
        return "http://www.edankert.com/examples/";
      } else if ...
        ...
      }
     
      return
XPathConstants .NULL_NS_URI;
    }
 
    public
String getPrefix( String namespaceURI) {
      if ( namespaceURI.equals( "http://www.edankert.com/examples/")) {
        return "edx";
      } else if ...
        ...
      } 
   
      return null;
    }
 
    public
Iterator getPrefixes( String namespaceURI) {
     
ArrayList list = new ArrayList ();
   
      if ( namespaceURI.equals( "http://www.edankert.com/examples/")) {
        list.add( "edx");
      } else if ...
        ...
      }
   
      return list.iterator();
    }
  });
 
 
Object nodes = xpath.evaluate( "//edx:cd", document.getDocumentElement(),
                                
XPathConstants .NODESET);
 
  ...
 
} catch (
ParserConfigurationException e) {
  ...
} catch (
XPathExpressionException e) {
  ...
} catch (
SAXException e) {
  ...
} catch (
IOException e) {
  ...
}
    首先用 JAXP 的 DocumentBuilderFactory 创建一个 org.w3c.dom.Document 对象,确保启用了 namespace 处理功能。
 
    现在可以通过 XPathFactory 来创建 XPath 对象,并通过 XPath 对象对文档进行查询。
 
    为了创建“前缀-命名空间”映射并传递给 XPath 引擎,我们需要实现 NamespaceContext 接口,该接口目前还没有默认实现类。这就意味着要实现 getNamespaceURI、getPrefix 和getPrefixes 方法,并确保这些方法能返回正确的值,包括“xmlns”和“xml”前缀所对应的命名空间的 URI 值。
 
    把我们自己实现的 NamespaceContext 对象传递给 XPath 引擎后,就可以通过 evaluate 方法来查询 XPath 表达式所对应的元素:使用上文中提到的 XPath 表达式,并使用 Document 的根节点作为输入入参数,并接收一个 NodeList 对象作为返回结果。

XSLT

    XPath 设计的初衷是用于 XSLT。这也许能解释“为什么在 XSLT 中定义命名空间的前缀是一件很平常的事”(也许因为 XSLT 也是一个 XML 名词的缘故吧)。 
 
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="//edx:cd" xmlns:edx="http://www.edankert.com/examples/">
    <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>
 
    只需要使用 XML 本身的机制,简单地为 edx 前缀赋予一个命名空间的 URI 值。
 
    通过与我们的 XPath 表达式“ //edx:cd”相匹配的  xsl:template,能得到与上文其他例子相同的输出结果。

结束语

    为了在(缺省)命名空间上使用 XPath 表达式,我们需要指定一个“前缀-命名空间”映射。正如我们所看到的,具体使用什么样的前缀名称,是无关紧要的。
 
    同样的方法,也可以用于查询那些用其他前缀修饰的元素。这意味着上面的例子对下述 XML 也有效。下述 XML 没有使用缺省命名空间,而是使用了 examples 作命名空间的前缀: 
 
<examples:catalog xmlns:examples="http://www.edankert.com/examples/">
  <examples:cd>
    <examples:artist>Sufjan Stevens</examples:artist>
    <examples:title>Illinois</examples:title>
    <examples:src>
[url]http://www.sufjan.com/</[/url] examples:src>
  </examples:cd>
  <examples:cd>
    <examples:artist>Stoat</examples:artist>
    <examples:title>Future come and get me</examples:title>
    <examples:src>
[url]http://www.stoatmusic.com/</[/url] examples:src>
  </examples:cd>
  <examples:cd>
    <examples:artist>The White Stripes</examples:artist>
    <examples:title>Get behind me satan</examples:title>
    <examples:src>
[url]http://www.whitestripes.com/</[/url] examples:src>
  </examples:cd>
</examples:catalog>
 
    使用“//edx:cd”作为 XPath 表达式,使用与前文例子相同的“前缀-命名空间”映射,在这个 XML 上同样能查询出属于“ [url]http://www.edankert.com/examples/[/url]”命名空间的所有“cd”元素。

资源

XPATH读取有命名空间的节点 XPATH读取有命名空间的节点 DOM4J 立即下载

相关推荐

常用的串口通信工具MobaXterm、Bus Hound、SScom等

本文介绍了四种PC端串口通信工具的功能和使用方法:MobaXterm支持SSH、FTP、串口等多种协议;Bus Hound用于监控CAN和串口数据;SScom专为串口和网口通信设计;ScriptCommunicator可进行串口通信并绘制波形图。每种工具都有详细的操作步骤图示,包括参数设置、数据监控等关键功能,并提供了官方和个人下载地址。这些工具各有特点,适用于不同的串口通信和数据分析场景。

sanqima的专栏 2488

添加命名空间后XPath的使用问题

诸如“为什么用 XPath 的表达式进行查询,却没有返回所期望的结果?”的问题通常都与命名空间(NameSpace)有关,而且绝大多数是与缺省命名空间(Default Namespace)有关。本文试图解释这个问题并针对三种流行的 XPath 实现给出解决方法:Jaxen、JAXP XPPathFactory 以及 XSLT。 内容列表 问题描述 “前缀-命名空间”映射 Jaxen

苍月 2990

手把手教你用XC7A35T FPGA搭建低成本机器视觉系统(含开发板选型指南)

本文详细介绍了如何利用AMD(原Xilinx)Artix-7系列中的XC7A35T FPGA芯片,搭建一套低成本的机器视觉系统。内容涵盖从芯片选型深度剖析、开发板(如黑金AX7035B)对比指南,到使用Vivado创建工程、编写图像处理模块(如RGB转灰度),以及资源优化和与上位机(如OpenCV)协同工作的完整流程,旨在为开发者提供一套可实践的高性价比硬件加速视觉解决方案。

beta5的博客 353

java xpath 默认命名空间_使用XML前缀/命名空间创建Xpath

这是我的prior question的后续内容 . 我想我跳到了深处,所以花一些时间完全理解XML命名空间 .从this XML页面开始,重点关注以下元素:我知道 m: 前缀用于区分 properties 元素与其他文档中具有相同名称的元素,以防这些文档被组合 . 我理解为了使用前缀,必须定义该前缀的命名空间 . 这样的定义是使用XML命名空间属性(xmlns)完成的,语法是 xmlns:pref...

weixin_27872611的博客 389

资产监测设备中130dBm的GPS信号注入天线端口,C/N0一般是多少?

笔者的团队一直从事于资产监测设备的开发,在开发过程中,涉及到很多细节的问题,针对新入职的同事来说较为陌生。同时,在团队外,还有需要对智能硬件终端开发感兴趣的用户。基于此背景下,笔者将在下面的内容主要介绍资产监测设备以及对设备中的GPS相关的问题:130dBm的GPS信号注入天线端口,C/N0一般是多少?作出详细的解答。 资产监测设备概述: 资产监测设备是基于物联网通信技术基础上的智能硬件终端,其主要作用是帮助用户监测资产在仓库、运输途中、交付整个流通环节中,提供资产的实时位置与状态参数。用户只需要登录资产

瑞奇聊通信模组 1229

用deepseek部署全自动的机器人--bytebot

Bytebot是一款开源AI桌面代理,提供完整的虚拟桌面环境,支持跨应用任务处理、文件管理、文档处理等复杂工作流。其技术架构包含核心控制、LLM代理、UI等组件,支持Docker和Kubernetes部署。本文演示了基于CloudStudio的部署流程,包括环境配置、Docker部署及DeepSeek API集成,实现多模型调用功能。

Kin 2481

java xpath使用_在XPath中使用Java语言NamespaceContext对象

先决条件和示例 在本文中,我假设您熟悉Brett McLaughlin的“从Java™平台评估XPath”中描述的技术细节。 如果你不知道如何使用XPath运行Java程序,请参阅Brett的文章(请参阅相关主题的文章链接。)同样是真实的加载一个XML文件,并评估XPath表达式所需的API 。 所有示例都将使用以下XML文件: 清单1.示例XML <?xml versio...

cusi77914的博客 909

【YOLOv8全方位学习手册】第四章 数据增强:从扩充数据到塑造模型的认知边界

"""使用 Albumentations 做自定义增强,兼容 YOLO 格式"""])# 转成 numpy# boxes 必须是 [[x_min,y_min,x_max,y_max], ...]# 在数据加载时调用你可以把集成到 PyTorch 的 Dataset 类里,或使用 Ultralytics 自带的DataLoader。

VectorShift的博客 211

xpath获取带命名空间节点注意事项

2. xpath取值必须通过//*[local-name()=’XXX’]来获取节点;1. xpath取值节点和属性都必须是。

Ghjkku的博客 11万+

3.1 快速启动Flink集群

在本实战中,我们将快速启动Apache Flink 1.13.0集群,并在Hadoop集群环境中提交作业。首先,我们会在本地下载Flink安装包并上传至云主机,解压并配置环境变量。接着,我们将启动Flink集群,通过访问Web UI进行监控管理。然后,我们会配置集群,将Flink分发到从节点,并在集群上提交作业。最后,我们将通过命令行提交作业,并在Web UI上查看任务节点的输出结果。这个过程涵盖了Flink集群的部署、配置和作业提交,为大数据处理提供了一个完整的实战经验。

howard2005的专栏 727

【OAG vs RAG】RAG的“语义崩溃“:为什么你的知识库越大,AI越笨?_语义检索oag-优快云博客

19.9 元(AI 编程 / Agent 实战 | 本文同主题系统课程)·49.9 元(AI 时代成长方法论)。单篇不过瘾?订阅解锁全量源码、实战与答疑;文末附资料包领取方式 ↓图1:RAG语义崩溃概念图。

求知若渴、虚心若愚 73

`javax.xml.transform` 是 Java 标准版(Java SE)中用于**XML 转换(XSLT)**的核心包

`javax.xml.transform` 是 Java 标准版(Java SE)中用于**XML 转换(XSLT)**的核心包,自 Java 1.5(JDK 5)引入,属于 JAXP(Java API for XML Processing)的一部分。它提供了一套面向接口的、可插拔的 API,用于将 XML 源(如 DOM、SAX、StAX 或 StreamSource)通过 XSLT 样式表转换为各种结果(如 DOM、SAX、StAX 或 OutputStream/Writer)。

[Blog][Domain] programb.blog.youkuaiyun.com 652

【WorkBuddy专栏19】技能的创造与迁移——从零开始打造你的AI工作流

【WorkBuddy专栏19】技能的创造与迁移——从零开始打造你的AI工作流

AI人人懂 371

XPath遇上命名空间

                我一直习惯用正则式来处理文本,包括XML文件,只是偶尔才用一下XmlDocument和XPath之类的东东。        最近做SP,移到的MISC系统从1.5升级到了1.6,它的1.5版用的是简单的XML格式响应和请求,现在的1.6版使用了标准的SOAP信息,一个标准的MISC对SP的请求可能是这样的: &lt;?xml version="1.0" encod...

weixin_34396103的博客 233

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

XPath的定义、基础语法、使用示例和高级用法

XPath(XMLPathLanguage)是一种用于在XML文档中定位和选择节点的语言,XPath的选择功能非常强大,可以通过简单的路径选择语法,选取文档中的任意节点或节点集,同样也支持HTML元素的解析,本文介绍了XPath的定义、基础语法、使用示例、高级用法、.NET中使用举例等

m0_70669463的博客 4220

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

使用XPath查询带有命名空间(有xmlns)的XML

最近碰到一个小问题,通过调用webservice返回如下的xml,   348388   Monsieur   FABRIZZI   FRANCIS   francis.fabrizzi@bayern-aix.net.bmw.fr   KUVOTFP   Chef de vente   francis.fabrizzi@bayern-aix.net.bmw.fr   0600

小肥的专栏 1万+

java xpath 默认命名空间_java – 如何在具有默认命名空间的xml文档上使用XPath

使用默认命名空间(无前缀)的文档的XPath处理与使用前缀的文档的XPath处理相同:对于命名空间限定文档,您可以在执行XPath时使用NamespaceContext.您将需要在XPath中的片段前缀匹配NamespaceContext.您使用的前缀不需要匹配文档中使用的前缀.以下是您的代码:import java.util.Iterator;import javax.xml.namespace...

weixin_35853464的博客 268

XML 命名空间(XML Namespaces)介绍以及节点读取方法

XML 命名空间提供避免元素命名冲突的方法。 命名冲突 在 XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。 这个 XML 文档携带着某个表格中的信息: <table> <tr> <td>Apples</td> <td>Bananas</td> </...

weixin_30354675的博客 912

java xpath 命名空间_【转】玩转 XPath 和缺省命名空间(Default Namespaces)

诸如“为什么用 XPath 的表达式进行查询,却没有返回所期望的结果?”的问题通常都与命名空间(NameSpace)有关,而且绝大多数是与缺省命名空间(Default Namespace)有关。本文试图解释这个问题并针对三种流行的 XPath 实现给出解决方法:Jaxen、JAXP XPPathFactory 以及 XSLT。内容列表1. 问题描述2. “前缀-命名空间”映射3. Jaxe...

weixin_39806388的博客 600

Dom4j 解析Atom 文档

第一种方法遍历Dom树,不使用xpath Element re=document.getRootElement(); List es=re.elements("entry"); for(int i=0;i<es.size();i++){ Element currentItem=(Element)es.get(i); Element title=(Element)currentI

xiaofanku的专栏 5633

dom4j 通过 org.dom4j.XPath 设置命名空间来支持 带namespace 的 xpath

测试文件 test.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.a...

weixin_30951231的博客 724

XPATH使用namespace

[code="java"]XPath xpath = XPathFactory.newInstance().newXPath(); NamespaceContext nsContext = new XHTMLNamespaceContext(); xpath.setNamespaceContext(nsContext); XPathExpression expr = xpath.co...

Nightlee 692

java的namespace_java – NamespaceContext并使用命名空间与XPath

没有编写自己的类就可以得到一个NamespaceContext实例.其class-use页显示可以使用javax.xml.stream包获得一个.String ctxtTemplate = "";NamespaceContext nsContext = null;XMLInputFactory factory = XMLInputFactory.newInstance();XMLEventRead...

weixin_35147832的博客 568

在XPath中指定namespace

abc 如果要解析上面的XML,需要如下指定XPath: /*[local-name() = 'test' and namespace-uri() = 'http://www.ca.com/']/*[local-name() = 'child' and namespace-uri() = 'http://www.w3.org/1999/xhtml'] 参考链接

冥想盆 1088
上一篇: 使用EXECUTE sp_executesql 避免SQL Injection
下一篇: JSTL choose + when + otherise的使用
dearls
博客等级 码龄19年 0粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值