这是我在大型XML处理过程中使用的类.

一些说明:

>对于任何元素,使用的xmlns声明来自此元素和所有祖先

>当元素< elem />是< elem xmlns =“x”/>的兄弟姐妹他们有不同的命名空间

>处理XML通常是基于堆栈的

码:

import java.util.Deque;

import java.util.HashMap;

import java.util.Iterator;

import java.util.LinkedList;

import java.util.Map;

import javax.xml.namespace.QName;

import org.springframework.util.xml.SimpleNamespaceContext;

import com.ximpleware.NavException;

import com.ximpleware.VTDNav;

public class VtdXmlCurrentState

{

/* Stack of QName.toString()s for the elements of processed XML - each is a full path */

private Deque qnames = new LinkedList();

/* Stack of QName.toString()s for the elements - each is a single path element and doesn't contain "/" */

private Deque names = new LinkedList();

// current depth in input document, starting from -1

private int currentDepth = -1;

// stack of namespace contexts increased during xml depth-first VTD navigation */

private Deque namespaces = new LinkedList();

// a flag for optimizing the case when there are many sibling elements without any xmlns declarations

// the case:

//

//

// ...

// it allows to effectively manage the stack and properly handles the following case:

//

//

// in which the second element should use NSContext from parent and not a copy of sibling's NSContext

private boolean lastNSContextsDifferent = false;

/**

*

*/

public VtdXmlCurrentState()

{

// first a context without any mapping

this.namespaces.push(new SimpleNamespaceContext());

// first QName is "/"

this.qnames.push("/");

this.names.push(null);

}

/**

* Name of the current element

* @return

*/

public QName currentElementName()

{

return this.names.peek();

}

/**

* Returns parent and current path for VTDNav

*

* @param nav

* @return

* @throws NavException

*/

public String[] currentXPath(VTDNav nav) throws NavException

{

// we don't check the end - autopilot handles that

int depth = nav.getCurrentDepth();

int idx = nav.getCurrentIndex();

this.handleNamespaces(nav, depth);

// determining current XPath

// name of the current element (optimization, because we're that the token is START_ELEMENT)

String elName = nav.toRawString(nav.getTokenOffset(idx), nav.getTokenLength(idx) & 0xffff);

QName qName = null;

if (elName.contains(":")) {

String[] qname = elName.split(":");

qName = new QName(this.namespaces.peek().getNamespaceURI(qname[0]), qname[1]);

} else {

qName = new QName(this.namespaces.peek().getNamespaceURI(""), elName);

}

// full name of the current element

StringBuilder sb = new StringBuilder(1024);

String fullName = null;

for (int i = 0; i <= this.currentDepth - depth; i++) {

this.qnames.pop();

this.names.pop();

}

fullName = sb.append(this.qnames.peek()).append(qName.toString()).append("/").toString();

String parentName = this.qnames.peek();

this.qnames.push(fullName);

this.names.push(qName);

this.currentDepth = depth;

return new String[] { parentName, fullName };

}

/**

* Handling element's namespaces - if there are any xmlns[:x], we must create new NSContext

*

* @param nav

* @param depth

* @throws NavException

*/

private void handleNamespaces(VTDNav nav, int depth) throws NavException

{

// are there any ns declarations?

Map _namespaces = null;

int index = nav.getCurrentIndex() + 1;

int total = nav.getTokenCount();

while (index < total) {

int type = nav.getTokenType(index);

while (type == VTDNav.TOKEN_ATTR_NAME) {

// quickly skip non-xmlns attrs

index += 2;

type = nav.getTokenType(index);

}

if (type == VTDNav.TOKEN_ATTR_NS) {

String prefix = nav.toString(index).substring(5);

if (prefix.length() > 0)

prefix = prefix.substring(1);

String namespace = nav.toString(index + 1);

if (_namespaces == null)

_namespaces = new HashMap();

_namespaces.put(prefix, namespace);

} else if (type == VTDNav.TOKEN_ATTR_VAL) {

} else {

break;

}

index++;

}

if (_namespaces != null) {

// first remove (if necessary) previous contexts from the stack - even if new element is at the same level

// (not descendant - it's sibiling), remove old, push new

for (int i = 0; i <= this.currentDepth - depth; i++)

this.namespaces.pop();

// for this element there's xmlns declaration - this element has different namespace context

// and it will be valid till the next descendant with xmlns

// previous context

SimpleNamespaceContext snc = this.namespaces.peek();

// new ...

SimpleNamespaceContext newSnc = new SimpleNamespaceContext();

// ... to which we'll copy previous declarations

for (Iterator> prefixes = snc.getBoundPrefixes(); prefixes.hasNext();) {

String pfx = (String)prefixes.next();

newSnc.bindNamespaceUri(pfx, snc.getNamespaceURI(pfx));

}

newSnc.bindNamespaceUri("", snc.getNamespaceURI(""));

// adding (overwriting!) new namespace mappings

newSnc.setBindings(_namespaces);

this.namespaces.push(newSnc);

this.lastNSContextsDifferent = true;

} else {

// current element doesn't define new namespaces - it gets them from parent element

// optimization - no new namesaces, the same level - we don't do anything!

// we only do something if we got a level up - we have to pop some ns contexts

for (int i = 0; i < this.currentDepth - depth; i++)

this.namespaces.pop();

if (this.currentDepth > depth) {

// we went up and popped() too much ns contexts - we duplicate the most recent

this.namespaces.push(this.namespaces.peek());

} else if (this.currentDepth < depth) {

// we went down - just copy

this.namespaces.push(this.namespaces.peek());

} else {

// the same level

if (this.lastNSContextsDifferent) {

this.namespaces.pop();

this.namespaces.push(this.namespaces.peek());

}

}

this.lastNSContextsDifferent = false;

}

}

}

输入XML:

使用课程:

byte[] doc = FileCopyUtils.copyToByteArray(super.createResource("dom03.xml").getInputStream());

VTDGen vtd = new VTDGen();

vtd.setDoc(doc);

vtd.parse(true);

VTDNav nav = vtd.getNav();

AutoPilot ap = new AutoPilot();

ap.bind(nav);

ap.selectElementNS("*", "*");

VtdXmlCurrentState cxp = new VtdXmlCurrentState();

ap.iterate();

assertEquals("/{urn:test:1.0}set/", cxp.currentXPath(nav)[1]);

ap.iterate();

assertEquals("/{urn:test:1.0}set/{urn:test:1.0}documents/", cxp.currentXPath(nav)[1]);

ap.iterate();

assertEquals("/{urn:test:1.0}set/{urn:test:1.0}documents/{urn:test:1.1}doc/", cxp.currentXPath(nav)[1]);

ap.iterate();

assertEquals("/{urn:test:1.0}set/{urn:test:1.0}documents/{urn:test:1.0}doc/", cxp.currentXPath(nav)[1]);

ap.iterate();

assertEquals("/{urn:test:1.0}set/{urn:test:1.0}documents/{urn:test:1.2}doc/", cxp.currentXPath(nav)[1]);

ap.iterate();

assertEquals("/{urn:test:1.0}set/{urn:test:1.0}documents/", cxp.currentXPath(nav)[1]);

ap.iterate();

assertEquals("/{urn:test:1.0}set/documents/", cxp.currentXPath(nav)[1]);

assertFalse(ap.iterate());

vtd xml java_java – 如何使用VTD-XML获取ONE元素的所有命名空间声明?相关推荐

  1. groupby java_Java流-在GroupBy之后获取内部元素

    这个问题已经在这里有了答案:            >            Java 8 grouping using custom collector?                    ...

  2. vue移除伪元素_获取伪元素的属性和改变伪元素的属性

    获取伪元素的属性值 获取伪元素的属性值可以使用window.getComputedStyle()方法,获取伪元素的CSS样式声明对象.然后利用getPropertyValue方法或直接使用键值访问都可 ...

  3. string to xml java_Java String to XML - Parse String to XML DOM Example - 入门小站-rumenz.com

    在Java中,XML用org.w3c.dom.Document对象表示. 在本XML教程中,我们将学习-将XML string to XML转换string to XML文档 将XML文件内容转换为X ...

  4. 【Groovy】Xml 反序列化 ( 使用 XmlParser 解析 Xml 文件 | 获取 Xml 文件中的节点和属性 | 获取 Xml 文件中的节点属性 )

    文章目录 一.创建 XmlParser 解析器 二.获取 Xml 文件中的节点 三.获取 Xml 文件中的节点属性 四.完整代码示例 一.创建 XmlParser 解析器 创建 XmlParser 解 ...

  5. webservice xml java_java访问WebService接口返回xml

    [      今天为了java webservice 为了调用NET,真是累死了,搞了整整一天.最后才搞定.唉,在网上搜了半天的资料,没有一个提供了正确的答案,都是抄来抄去的,或者高手们都太低调 pa ...

  6. java中获取XML中的子xml_如何将子元素从XML提取到Java中的字符串?

    小编典典 没错,使用标准XML API并不是一种好方法-这是一个示例(可能是bug缠身:它可以运行,但是我很久以前就写了). import javax.xml.*; import javax.xml. ...

  7. php xml对象解析_php解析xml 的四种简单方法(附实例)

    XML处理是开发过程中经常遇到的,PHP对其也有很丰富的支持,本文只是对其中某几种解析技术做简要说明,包括:Xml parser, SimpleXML, XMLReader, DOMDocument. ...

  8. iOS -数据库网络之xml解析之远程解析XML

    1.IOS中XML文件获取    //设置远程访问地址     NSURL *url=[NSURL URLWithString:@""];       //创建动态URL请求,并初 ...

  9. 【Groovy】xml 序列化 ( 使用 MarkupBuilder 生成 xml 数据 | 标签闭包下创建子标签 | 使用 MarkupBuilderHelper 添加 xml 注释 )

    文章目录 一.标签闭包下创建子标签 二.使用 MarkupBuilderHelper 添加 xml 注释 三.完整代码示例 一.标签闭包下创建子标签 在上一篇博客 [Groovy]xml 序列化 ( ...

最新文章

  1. Go 语言编程 — 高级数据类型 — Slice 切片
  2. multipart/form-data ajax 提交问题(未解决)
  3. String比较? 用==判断两个字符串,有时为true有时为false
  4. Hashtable排序
  5. 二叉树的递归遍历与复制
  6. Opencv——霍夫变换以及遇到的一些问题
  7. 如何为Kafka挑选合适的分区数
  8. TensorFlow 还是 PyTorch?哪一个才更适合编写深度神经网络?
  9. SQLite 的日期时间函数
  10. 两篇介绍IIS的文章
  11. 动态路由之OSPF协议综合实验
  12. php连接mysql字符串函数_mysql 字符串函数
  13. 大一C语言和线性代数,线性代数:对于编程很重要
  14. 在HTML中什么表示水平线,HTML中加入水平线的标签是( )
  15. 分布式文件系统 FastDFS 5.0.5 Linux CentOS 7 安装配置
  16. C#中操作Word(7)—— 如何向Word中插入表格
  17. 使用 mongorestore恢复数据以及使用 Studio 3T GUI 管理数据库
  18. Win 10出现bitlocke恢复,蓝屏错误代码0x1600007e
  19. 多对多关系需要建立中间表_【数据库基础】为什么需要三张表之多对多表结构设计...
  20. docker配置redis

热门文章

  1. MATLAB绘制正弦函数与余弦函数的线性组合曲线
  2. 跨浏览器和跨平台甘特图dhtmlxGantt,选择它的6个理由!
  3. 优秀自我简介200字_优秀初中自我介绍200字范文
  4. .net framework 4.5 未指定的错误
  5. 最新旧物回收类网站源码V2.4版+Thinkphp内核
  6. 【算法】遗传算法及其 Java 实现
  7. CCNA精品学习资料汇总(学习手册+笔记+题库)
  8. 当手机产业进入硬件能力过剩时代
  9. 找不到动态库解决方案
  10. 几种常用的噪声估计算法(二)