XML API 或开源 jar,用于根据给定路径提取 XML 的子集
XML API or open source jar for extract a subset of XML based on a given path
我想知道是否有 API 或开源 jar 可以根据给定路径提取 XML 的子集。
例如:
我有一个XML,它是一个骨架(阴模型,由阳模型转换而来)
<xml .....>
<data>
<model1>
<element1>
<id />
<name />
<address />
</element1>
</model1>
<model2>
<element2>
<uid />
<something />
</element2>
</model2>
....
</data>
给定路径:
data/model1/element1[id='1']/name and name value is 'John'
我希望返回以下内容
<xml .....>
<data>
<model1>
<element1>
<id>1</id>
<name>John</name>
</element1>
</model1>
<data>
我不太确定要搜索什么关键字。希望有足够了解 XML 的人可以提出建议。
另一个问题是,如果没有现成的 API 或开源,处理这个问题的最佳方法是什么?我应该使用 DOM 因为我需要骨架中的整个(树)结构吗?除了 DOM 占用太多内存外,其他副作用是什么?
您可以使用内置包javax.xml
来读写数据。您可以使用 XML path language (XPath) 查询 XML。比如提取<element1>
:
的子树
/data/model1/element1
或提取 <element1>
的子树,其中 child-elements <id>
有文本“1”:
/data/model1/element1[id/text() = 1]
我写了一个小程序来演示用法。你需要
- 创建
org.w3c.dom.Document
- 将 XML 内容解析到此对象中
- 编译您的 XPath 表达式
- 使用编译后的 xpath 作为
NodeList
提取文档
- 导出
NodeList
或执行任何其他需要的任务。
您可以按如下方式编译程序和运行:
$ javac Demo.java
$ java Demo /data/model1/element1
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
<model1>
<element1>
<id>1</id>
<name>John</name>
<address>xxx</address>
</element1>
<element1>
<id>2</id>
<name>Tom</name>
<address>yyy</address>
</element1>
</model1>
</data>
~ $ java Demo '/data/model1/element1[id/text() = 1]'
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
<model1>
<element1>
<id>1</id>
<name>John</name>
<address>xxx</address>
</element1>
</model1>
</data>
完整程序:
import java.io.*;
import java.nio.charset.StandardCharsets;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class Demo {
private static final String XML =
"<?xml version=\"1.0\"?>\n"
+ "<data>\n"
+ " <model1>\n"
+ " <element1>\n"
+ " <id>1</id>\n"
+ " <name>John</name>\n"
+ " <address>xxx</address>\n"
+ " </element1>\n"
+ " <element1>\n"
+ " <id>2</id>\n"
+ " <name>Tom</name>\n"
+ " <address>yyy</address>\n"
+ " </element1>\n"
+ " </model1>\n"
+ " <model2>\n"
+ " <element2>\n"
+ " <uid />\n"
+ " <something />\n"
+ " </element2>\n"
+ " </model2>"
+ "</data>";
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document source;
try (InputStream in = new ByteArrayInputStream(XML.getBytes(StandardCharsets.UTF_8))) {
source = factory.newDocumentBuilder().parse(in);
}
// Extract
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile(args[0]);
NodeList nodeList = (NodeList) expr.evaluate(source, XPathConstants.NODESET);
// Export
Document target = factory.newDocumentBuilder().newDocument();
Element data = target.createElement("data");
Element model1 = target.createElement("model1");
data.appendChild(model1);
target.appendChild(data);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
Node newNode = target.importNode(node, true);
model1.appendChild(newNode);
}
System.out.println(getStringFrom(target));
}
private static String getStringFrom(Document doc) throws TransformerException {
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
// set indent
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(domSource, result);
return writer.toString();
}
}
我想知道是否有 API 或开源 jar 可以根据给定路径提取 XML 的子集。
例如: 我有一个XML,它是一个骨架(阴模型,由阳模型转换而来)
<xml .....>
<data>
<model1>
<element1>
<id />
<name />
<address />
</element1>
</model1>
<model2>
<element2>
<uid />
<something />
</element2>
</model2>
....
</data>
给定路径:
data/model1/element1[id='1']/name and name value is 'John'
我希望返回以下内容
<xml .....>
<data>
<model1>
<element1>
<id>1</id>
<name>John</name>
</element1>
</model1>
<data>
我不太确定要搜索什么关键字。希望有足够了解 XML 的人可以提出建议。
另一个问题是,如果没有现成的 API 或开源,处理这个问题的最佳方法是什么?我应该使用 DOM 因为我需要骨架中的整个(树)结构吗?除了 DOM 占用太多内存外,其他副作用是什么?
您可以使用内置包javax.xml
来读写数据。您可以使用 XML path language (XPath) 查询 XML。比如提取<element1>
:
/data/model1/element1
或提取 <element1>
的子树,其中 child-elements <id>
有文本“1”:
/data/model1/element1[id/text() = 1]
我写了一个小程序来演示用法。你需要
- 创建
org.w3c.dom.Document
- 将 XML 内容解析到此对象中
- 编译您的 XPath 表达式
- 使用编译后的 xpath 作为
NodeList
提取文档
- 导出
NodeList
或执行任何其他需要的任务。
您可以按如下方式编译程序和运行:
$ javac Demo.java
$ java Demo /data/model1/element1
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
<model1>
<element1>
<id>1</id>
<name>John</name>
<address>xxx</address>
</element1>
<element1>
<id>2</id>
<name>Tom</name>
<address>yyy</address>
</element1>
</model1>
</data>
~ $ java Demo '/data/model1/element1[id/text() = 1]'
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data>
<model1>
<element1>
<id>1</id>
<name>John</name>
<address>xxx</address>
</element1>
</model1>
</data>
完整程序:
import java.io.*;
import java.nio.charset.StandardCharsets;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class Demo {
private static final String XML =
"<?xml version=\"1.0\"?>\n"
+ "<data>\n"
+ " <model1>\n"
+ " <element1>\n"
+ " <id>1</id>\n"
+ " <name>John</name>\n"
+ " <address>xxx</address>\n"
+ " </element1>\n"
+ " <element1>\n"
+ " <id>2</id>\n"
+ " <name>Tom</name>\n"
+ " <address>yyy</address>\n"
+ " </element1>\n"
+ " </model1>\n"
+ " <model2>\n"
+ " <element2>\n"
+ " <uid />\n"
+ " <something />\n"
+ " </element2>\n"
+ " </model2>"
+ "</data>";
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document source;
try (InputStream in = new ByteArrayInputStream(XML.getBytes(StandardCharsets.UTF_8))) {
source = factory.newDocumentBuilder().parse(in);
}
// Extract
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile(args[0]);
NodeList nodeList = (NodeList) expr.evaluate(source, XPathConstants.NODESET);
// Export
Document target = factory.newDocumentBuilder().newDocument();
Element data = target.createElement("data");
Element model1 = target.createElement("model1");
data.appendChild(model1);
target.appendChild(data);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
Node newNode = target.importNode(node, true);
model1.appendChild(newNode);
}
System.out.println(getStringFrom(target));
}
private static String getStringFrom(Document doc) throws TransformerException {
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
// set indent
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(domSource, result);
return writer.toString();
}
}