英文:
How can i create a new XML parents for elements which are between two boundary elements
问题
我想在JDOM2结构中的两个边界元素之间创建一个新的XML父元素,尽可能高的级别。
实际上,对于<start>
和<stop>
元素的放置没有限制。
简化示例:
<root>
<a>
<ax>
<start></start>
</ax>
<ay></ay>
<az></az>
</a>
<b>
<bx></bx>
</b>
<c>
<cx></cx>
<cy></cy>
<cz>
<cza></cza>
<czb>
<stop></stop>
</czb>
</cz>
</c>
</code>
输出:
```xml
<root>
<a>
<ax>
<start></start>
</ax>
<added>
<ay></ay>
<az></az>
</added>
</a>
<added>
<b>
<bx></bx>
</b>
</added>
<c>
<added>
<cx></cx>
<cy></cy>
</added>
<cz>
<added>
<cza></cza>
</added>
<czb>
<stop></stop>
</czb>
</cz>
</c>
</code>
英文:
I would like to create a new XML parents at the highest possible levels for elements which are between two boundary elements in the JDOM2 structure.
Practically there are no limitations to the placement of the <start>
and <stop>
elements.
Simplified example:
<root>
<a>
<ax>
<start></start>
</ax>
<ay></ay>
<az></az>
</a>
<b>
<bx></bx>
</b>
<c>
<cx></cx>
<cy></cy>
<cz>
<cza></cza>
<czb>
<stop></stop>
</czb>
</cz>
</c>
output:
<root>
<a>
<ax>
<start></start>
</ax>
<added>
<ay></ay>
<az></az>
</added>
</a>
<added>
<b>
<bx></bx>
</b>
</added>
<c>
<added>
<cx></cx>
<cy></cy>
</added>
<cz>
<added>
<cza></cza>
</added>
<czb>
<stop></stop>
</czb>
</cz>
</c>
答案1
得分: 1
以下是一些关于使用XQuery 3.1的尝试,用于识别和包装元素的示例代码。您可以在Java中使用Saxon HE或BaseX运行它,但不确定对于JDOM的哪个库可以使用,我认为Saxon支持它。示例代码如下:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'xml';
declare option output:indent 'yes';
declare function local:transform($node as node(), $siblings-to-be-wrapped as array(element()*)*) {
typeswitch ($node)
case document-node()
return document { $node!node()!local:transform(., $siblings-to-be-wrapped) }
case element()
return
let $match := $siblings-to-be-wrapped[some $el in ?* satisfies $el is $node]
return if ($node is $match?1)
then <added>{$match}</added>
else if (not(exists($match)))
then element { node-name($node) } { $node!@*, $node!node()!local:transform(., $siblings-to-be-wrapped) }
else ()
default
return $node
};
let $start-elements := //start,
$stop-elements := //stop,
$siblings-to-be-wrapped := for-each-pair(
$start-elements,
$stop-elements,
function($s, $e) {
let $elements-to-be-wrapped := outermost(root($s)//*[. >> $s and . << $e][not(some $d in .//* satisfies ($d is $s or $d is $e))])
for tumbling window $siblings in $elements-to-be-wrapped
start $s when true()
end next $n when not($s/.. is $n/..)
return array { $siblings }
}
)
return
local:transform(/, $siblings-to-be-wrapped)
这段代码的作用是识别特定的起始元素和停止元素之间的元素,并将它们包装在
如果您要在Saxon HE中运行这个XQuery代码,可以使用下面的Java代码:
import net.sf.saxon.s9api.*;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException, SaxonApiException {
Processor processor = new Processor();
DocumentBuilder docBuilder = processor.newDocumentBuilder();
XdmNode inputDoc = docBuilder.build(new File("sample1.xml"));
XQueryCompiler xqueryCompiler = processor.newXQueryCompiler();
XQueryExecutable xqueryExecutable = xqueryCompiler.compile(new File("wrap-siblings-between-milestones1.xq"));
XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
xqueryEvaluator.setContextItem(inputDoc);
xqueryEvaluator.run(processor.newSerializer(System.out));
}
}
这个Java代码用于加载XML文档并运行XQuery代码,将结果输出到System.out。
如果您要在Saxon HE中使用JDOM2,您需要下载源代码并将net.sf.saxon.option.jdom2
包编译到您的Java项目中。然后,您可以使用以下Java代码来运行XQuery代码并返回新的JDOM文档:
import net.sf.saxon.option.jdom2.JDOM2ObjectModel;
import net.sf.saxon.s9api.*;
import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.transform.JDOMResult;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException, SaxonApiException, JDOMException {
Processor processor = new Processor();
processor.getUnderlyingConfiguration().registerExternalObjectModel(new JDOM2ObjectModel());
Document jdomDocument = new SAXBuilder().build(new File("sample1.xml"));
DocumentBuilder docBuilder = processor.newDocumentBuilder();
XdmNode inputDoc = docBuilder.wrap(jdomDocument);
XQueryCompiler xqueryCompiler = processor.newXQueryCompiler();
XQueryExecutable xqueryExecutable = xqueryCompiler.compile(new File("wrap-siblings-between-milestones1.xq"));
XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
xqueryEvaluator.setContextItem(inputDoc);
JDOMResult jdomResult = new JDOMResult();
xqueryEvaluator.run(new SAXDestination(jdomResult.getHandler()));
Document resultDoc = jdomResult.getDocument();
XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
xmlOutputter.output(resultDoc, System.out);
}
}
这个Java代码用于加载JDOM文档并运行XQuery代码,然后将结果输出到System.out。希望这些信息对您有所帮助。
英文:
Here is some attempt in XQuery 3.1 (which you can run with Java using Saxon HE or BaseX, not sure whether for both over JDOM, I think Saxon supports that https://www.saxonica.com/html/documentation11/sourcedocs/tree-models/thirdparty.html) to identify and wrap the elements e.g.
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'xml';
declare option output:indent 'yes';
declare function local:transform($node as node(), $siblings-to-be-wrapped as array(element()*)*) {
typeswitch ($node)
case document-node()
return document { $node!node()!local:transform(., $siblings-to-be-wrapped) }
case element()
return
let $match := $siblings-to-be-wrapped[some $el in ?* satisfies $el is $node]
return if ($node is $match?1)
then <added>{$match}</added>
else if (not(exists($match)))
then element { node-name($node) } { $node!@*, $node!node()!local:transform(., $siblings-to-be-wrapped) }
else ()
default
return $node
};
let $start-elements := //start,
$stop-elements := //stop,
$siblings-to-be-wrapped := for-each-pair(
$start-elements,
$stop-elements,
function($s, $e) {
let $elements-to-be-wrapped := outermost(root($s)//*[. >> $s and . << $e][not(some $d in .//* satisfies ($d is $s or $d is $e))])
for tumbling window $siblings in $elements-to-be-wrapped
start $s when true()
end next $n when not($s/.. is $n/..)
return array { $siblings }
}
)
return
local:transform(/, $siblings-to-be-wrapped)
Result is e.g.
<root>
<a>
<ax>
<start/>
</ax>
<added>
<ay/>
<az/>
</added>
</a>
<added>
<b>
<bx/>
</b>
</added>
<c>
<added>
<cx/>
<cy/>
</added>
<cz>
<added>
<cza/>
</added>
<czb>
<stop/>
</czb>
</cz>
</c>
</root>
Not well tested and currently, like in the shown input sample, looking only for element nodes to be wrapped, not expecting mixed contents with text nodes split by e.g. <start/>
and <stop/>
.
Minimal Saxon HE (used 12.3) code to run XQuery against an input file and output the result (for testing to System.out) is e.g.
import net.sf.saxon.s9api.*;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException, SaxonApiException {
Processor processor = new Processor();
DocumentBuilder docBuilder = processor.newDocumentBuilder();
XdmNode inputDoc = docBuilder.build(new File("sample1.xml"));
XQueryCompiler xqueryCompiler = processor.newXQueryCompiler();
XQueryExecutable xqueryExecutable = xqueryCompiler.compile(new File("wrap-siblings-between-milestones1.xq"));
XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
xqueryEvaluator.setContextItem(inputDoc);
xqueryEvaluator.run(processor.newSerializer(System.out));
}
}
Example online: https://github.com/martin-honnen/SaxonXQueryWrapSiblingsBetweenMileStones
To use JDOM2 with Saxon HE you need to download the source from https://github.com/Saxonica/Saxon-HE/tree/main/12/source and compile the net.sf.saxon.option.jdom2
package into your Java project (and it seems comment out line 50 in JDOM2DocumentWrapper.java before you do that), then the code to run XQuery on the JDOM Document and return a new one is e.g.
import net.sf.saxon.option.jdom2.JDOM2ObjectModel;
import net.sf.saxon.s9api.*;
import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.transform.JDOMResult;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException, SaxonApiException, JDOMException {
Processor processor = new Processor();
processor.getUnderlyingConfiguration().registerExternalObjectModel(new JDOM2ObjectModel());
Document jdomDocument = new SAXBuilder().build(new File("sample1.xml"));
DocumentBuilder docBuilder = processor.newDocumentBuilder();
XdmNode inputDoc = docBuilder.wrap(jdomDocument);
XQueryCompiler xqueryCompiler = processor.newXQueryCompiler();
XQueryExecutable xqueryExecutable = xqueryCompiler.compile(new File("wrap-siblings-between-milestones1.xq"));
XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
xqueryEvaluator.setContextItem(inputDoc);
JDOMResult jdomResult = new JDOMResult();
xqueryEvaluator.run(new SAXDestination(jdomResult.getHandler()));
Document resultDoc = jdomResult.getDocument();
XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
xmlOutputter.output(resultDoc, System.out);
}
}
Example online: https://github.com/martin-honnen/SaxonXQueryWrapSiblingsBetweenMileStones/tree/UseJDOM
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论