Java XML:将深度对齐结构转换为宽度对齐结构
这个问题涉及到一个我们还没有找到的算法。问题如下: 我们有一个包含深度对齐结构的XML(具体来说是包含content.XML的ODT文件):Java XML:将深度对齐结构转换为宽度对齐结构,java,xml,structure,flat,Java,Xml,Structure,Flat,这个问题涉及到一个我们还没有找到的算法。问题如下: 我们有一个包含深度对齐结构的XML(具体来说是包含content.XML的ODT文件): <root xmlns:text="someuri"> <header> ... </header> <body> <text:span dns:att01="value"> some text </text:span> <text:spa
<root xmlns:text="someuri">
<header>
...
</header>
<body>
<text:span dns:att01="value">
some text
</text:span>
<text:span dns:att02="value">
more text
<text:span dns:att03="value">
even nested structures
</text:span>
</text:span>
</body>
</root>
...
一些文本
更多文本
偶数嵌套结构
请注意,这是一个仅包含必要细节的简化示例。如您所见,这看起来像一个“普通”xml结构,根包含一些文本和跨节点。对于我们的应用程序,我们需要进行一些处理。由于所有跨度节点都包含其他节点,形成树状结构,因此需要转换目标格式以使文本节点宽度对齐。这是所需的格式:
<root xmlns:text="someuri">
<header>
...
</header>
<body>
<text:marker-begin text:name="01" />
some text
<text:marker-end text:name="01" />
<text:marker text:name="01" />
<text:marker-begin text:name="02" />
more text
<text:marker-begin text:name="03" />
even nested structures
<text:marker-end text:name="03" />
<text:marker text:name="03" />
<text:marker-end text:name="02" />
<text:marker text:name="02" />
</body>
</root>
...
一些文本
更多文本
偶数嵌套结构
不要让缩进激怒你,因为除了body节点之外,所有文本节点都可能有一个直接的父节点。该标记用于从第三方软件触发特定功能。所需的文本注释现在由包含标记机制的空元素包围。现在,经过详细的准备,问题本身:
如何使用java提供的默认DOM机制将结构1转换为结构2。这可能吗?您是否愿意建议使用SAX方法来收集span节点的开始和结束元素?是否已经存在解决此问题的算法?XLST是不可能的,因为侧处理链必须在处理过程中完成 我们通过使用一个肮脏的技巧找到了一个解决方案: 我们有一个遍历器的广度优先实现(这里使用TreeWalker没有任何意义)将所需的操作委托给处理函数:
// local field
Queue queue;
void traverse()
{
queue = new LinkedListed();
queue.add(documentRoot);
queue.add(root);
while (!queue.isEmpty())
{
current = queue.poll();
children = current.getChildNodes();
// the delegate
process(current);
for (int i = 0; i < children.getLength(); i++)
{
child = children.item(i);
switch(child.getNodeType())
{
case Node.ELEMENT_NODE:
case Node.TEXT_NODE:
queue.add(child);
break;
}
} // end iteration over childnodes
}
}
void process(Node node)
{
String name = node.getNodeName();
Map<String, String> attributes = XMLUtil.extractAttributes(node);
// this is basically the current node, but we need to save it as
// extra reference to copy all child elements from it, to further process
// the document tree
Node target = null;
Node next = null;
Node parent = node.getParentNode();
if(name.equals("text:" + TARGET_ELEMENT)) {
// deep copy
target = node.cloneNode(true);
// create the three relevant bookmark nodes
Node bkMrkStart = document.createElement("bookmark-begin");
Node bkMrkEnd = document.createElement("bookmark-end");
Node bkMrkRsd = document.createElement("bookmark");
// insert bookmark start
node.getParentNode().insertBefore(bkMrkStart, node);
// get next sibling or null, if last elment
next = node.getNextSibling();
// insert ending bookmark and 'residue'
parent.insertBefore(bkMrkRsd, next);
parent.insertBefore(bkMrkEnd, bkMrkRsd);
// create new its tag element
AuxiliaryElement nextAux = createAuxiliary(attributes);
// apply generated id to created bookmarks
XMLUtil.setAttribute(
"text:span",
"id-[" + nextAux.getId().getString() + "]",
bkMrkStart, bkMrkEnd, bkMrkRsd);
NodeList children = target.getChildNodes();
int index = 0;
do
{
Node child = children.item(index).cloneNode(true);
// it seems necessary to extra save this element
// for further processing
queue.add(child);
parent.insertBefore(child, bkMrkEnd);
} while(++index < children.getLength());
// delete old element
parent.removeChild(node);
// clear target
target = null;
}
}
//本地字段
排队;
无效遍历()
{
队列=新的LinkedListed();
添加(documentRoot);
添加(根);
而(!queue.isEmpty())
{
current=queue.poll();
children=current.getChildNodes();
//代表
过程(当前);
for(int i=0;i
这里是处理函数:
// local field
Queue queue;
void traverse()
{
queue = new LinkedListed();
queue.add(documentRoot);
queue.add(root);
while (!queue.isEmpty())
{
current = queue.poll();
children = current.getChildNodes();
// the delegate
process(current);
for (int i = 0; i < children.getLength(); i++)
{
child = children.item(i);
switch(child.getNodeType())
{
case Node.ELEMENT_NODE:
case Node.TEXT_NODE:
queue.add(child);
break;
}
} // end iteration over childnodes
}
}
void process(Node node)
{
String name = node.getNodeName();
Map<String, String> attributes = XMLUtil.extractAttributes(node);
// this is basically the current node, but we need to save it as
// extra reference to copy all child elements from it, to further process
// the document tree
Node target = null;
Node next = null;
Node parent = node.getParentNode();
if(name.equals("text:" + TARGET_ELEMENT)) {
// deep copy
target = node.cloneNode(true);
// create the three relevant bookmark nodes
Node bkMrkStart = document.createElement("bookmark-begin");
Node bkMrkEnd = document.createElement("bookmark-end");
Node bkMrkRsd = document.createElement("bookmark");
// insert bookmark start
node.getParentNode().insertBefore(bkMrkStart, node);
// get next sibling or null, if last elment
next = node.getNextSibling();
// insert ending bookmark and 'residue'
parent.insertBefore(bkMrkRsd, next);
parent.insertBefore(bkMrkEnd, bkMrkRsd);
// create new its tag element
AuxiliaryElement nextAux = createAuxiliary(attributes);
// apply generated id to created bookmarks
XMLUtil.setAttribute(
"text:span",
"id-[" + nextAux.getId().getString() + "]",
bkMrkStart, bkMrkEnd, bkMrkRsd);
NodeList children = target.getChildNodes();
int index = 0;
do
{
Node child = children.item(index).cloneNode(true);
// it seems necessary to extra save this element
// for further processing
queue.add(child);
parent.insertBefore(child, bkMrkEnd);
} while(++index < children.getLength());
// delete old element
parent.removeChild(node);
// clear target
target = null;
}
}
void流程(节点)
{
字符串名称=node.getNodeName();
映射属性=XMLUtil.extractAttributes(节点);
//这基本上是当前节点,但我们需要将其另存为
//用于将所有子元素从中复制到进一步处理的额外引用
//文档树
节点目标=null;
Node next=null;
Node parent=Node.getParentNode();
if(name.equals(“文本:+TARGET_元素)){
//深度复制
target=node.cloneNode(true);
//创建三个相关的书签节点
节点bkMrkStart=document.createElement(“书签开始”);
节点bkMrkEnd=document.createElement(“书签结束”);
节点bkMrkRsd=document.createElement(“书签”);
//插入书签开始
node.getParentNode().insertBefore(bkMrkStart,node);
//获取下一个同级或null(如果是最后一个elment)
next=node.getNextSibling();
//插入结尾书签和“剩余”
parent.insertBefore(bkMrkRsd,next);
parent.insertBefore(bkMrkEnd,bkMrkRsd);
//创建新的its标记元素
辅助元素nextAux=createAuxiliary(属性);
//将生成的id应用于已创建的书签
XMLUtil.setAttribute(
“文本:span”,
“id-[”+nextAux.getId().getString()+“]”,
bkMrkStart、bkMrkEnd、bkMrkRsd);
NodeList childrends=target.getChildNodes();
int指数=0;
做
{
Node child=children.item(index.cloneNode)(true);
//似乎有必要额外保存此元素
//作进一步处理
添加(子级);
parent.insertBefore(child,bkMrkEnd);
}而(++index
看起来#removeChild或#insertBefore没有被遍历反映出来。这可能是因为我们自己实现了广度优先遍历器。但是,使用上述方法可以获得理想的结果。如果有人有更好的解决方案,可以给出提示,说明这里哪里做错了,什么味道,请提供解决方案。我们一定会感谢你的!:)