vtd xml java_java – 如何使用VTD-XML获取ONE元素的所有命名空间声明?
这是我在大型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元素的所有命名空间声明?相关推荐
- groupby java_Java流-在GroupBy之后获取内部元素
这个问题已经在这里有了答案: > Java 8 grouping using custom collector? ...
- vue移除伪元素_获取伪元素的属性和改变伪元素的属性
获取伪元素的属性值 获取伪元素的属性值可以使用window.getComputedStyle()方法,获取伪元素的CSS样式声明对象.然后利用getPropertyValue方法或直接使用键值访问都可 ...
- 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 ...
- 【Groovy】Xml 反序列化 ( 使用 XmlParser 解析 Xml 文件 | 获取 Xml 文件中的节点和属性 | 获取 Xml 文件中的节点属性 )
文章目录 一.创建 XmlParser 解析器 二.获取 Xml 文件中的节点 三.获取 Xml 文件中的节点属性 四.完整代码示例 一.创建 XmlParser 解析器 创建 XmlParser 解 ...
- webservice xml java_java访问WebService接口返回xml
[ 今天为了java webservice 为了调用NET,真是累死了,搞了整整一天.最后才搞定.唉,在网上搜了半天的资料,没有一个提供了正确的答案,都是抄来抄去的,或者高手们都太低调 pa ...
- java中获取XML中的子xml_如何将子元素从XML提取到Java中的字符串?
小编典典 没错,使用标准XML API并不是一种好方法-这是一个示例(可能是bug缠身:它可以运行,但是我很久以前就写了). import javax.xml.*; import javax.xml. ...
- php xml对象解析_php解析xml 的四种简单方法(附实例)
XML处理是开发过程中经常遇到的,PHP对其也有很丰富的支持,本文只是对其中某几种解析技术做简要说明,包括:Xml parser, SimpleXML, XMLReader, DOMDocument. ...
- iOS -数据库网络之xml解析之远程解析XML
1.IOS中XML文件获取 //设置远程访问地址 NSURL *url=[NSURL URLWithString:@""]; //创建动态URL请求,并初 ...
- 【Groovy】xml 序列化 ( 使用 MarkupBuilder 生成 xml 数据 | 标签闭包下创建子标签 | 使用 MarkupBuilderHelper 添加 xml 注释 )
文章目录 一.标签闭包下创建子标签 二.使用 MarkupBuilderHelper 添加 xml 注释 三.完整代码示例 一.标签闭包下创建子标签 在上一篇博客 [Groovy]xml 序列化 ( ...
最新文章
- Go 语言编程 — 高级数据类型 — Slice 切片
- multipart/form-data ajax 提交问题(未解决)
- String比较? 用==判断两个字符串,有时为true有时为false
- Hashtable排序
- 二叉树的递归遍历与复制
- Opencv——霍夫变换以及遇到的一些问题
- 如何为Kafka挑选合适的分区数
- TensorFlow 还是 PyTorch?哪一个才更适合编写深度神经网络?
- SQLite 的日期时间函数
- 两篇介绍IIS的文章
- 动态路由之OSPF协议综合实验
- php连接mysql字符串函数_mysql 字符串函数
- 大一C语言和线性代数,线性代数:对于编程很重要
- 在HTML中什么表示水平线,HTML中加入水平线的标签是( )
- 分布式文件系统 FastDFS 5.0.5 Linux CentOS 7 安装配置
- C#中操作Word(7)—— 如何向Word中插入表格
- 使用 mongorestore恢复数据以及使用 Studio 3T GUI 管理数据库
- Win 10出现bitlocke恢复,蓝屏错误代码0x1600007e
- 多对多关系需要建立中间表_【数据库基础】为什么需要三张表之多对多表结构设计...
- docker配置redis