java - 使用 StAX 对 XML 进行简单修改
问题描述
我试图修改现有的 XML 文件。据我所知,不可能直接即时执行,所以我的想法是读取流中的文件,修改它,创建一个新文件,然后用新文件替换旧文件。
我只需要应用简单的更改,因此我决定采用 StAX 方法,因为它更适合大量数据或简单处理。
现有的 XML 文件:
<?xml version='1.0' encoding='UTF-8'?>
<Company>
<Employee>
<FirstName>Tanmay</FirstName>
<LastName>Patil</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Bangalore</City>
<State>Karnataka</State>
<Zip>560212</Zip>
</Address>
</Employee>
</Company>
期望的输出:
<?xml version='1.0' encoding='UTF-8'?>
<Company>
<Employee>
<FirstName>Tanmay</FirstName>
<LastName>Patil</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Bangalore</City>
<State>Karnataka</State>
<NewElem>Some value</NewElem> <!-- Replacing all ZIP-elements -->
</Address>
</Employee>
</Company>
这段代码只是复制了一个 XML 文件(source):
public static void writeAll(XMLStreamReader xmlr, XMLStreamWriter writer)
throws XMLStreamException {
while (xmlr.hasNext()) {
write(xmlr, writer);
xmlr.next();
}
write(xmlr, writer); // write the last element
writer.flush();
}
public static void write(XMLStreamReader xmlr, XMLStreamWriter writer) throws XMLStreamException {
switch (xmlr.getEventType()) {
case XMLEvent.START_ELEMENT:
final String localName = xmlr.getLocalName();
final String namespaceURI = xmlr.getNamespaceURI();
if (namespaceURI != null && namespaceURI.length() > 0) {
final String prefix = xmlr.getPrefix();
if (prefix != null) {
writer.writeStartElement(prefix, localName, namespaceURI);
} else {
writer.writeStartElement(namespaceURI, localName);
}
} else {
writer.writeStartElement(localName);
}
for (int i = 0, len = xmlr.getNamespaceCount(); i < len; i++) {
writer.writeNamespace(xmlr.getNamespacePrefix(i), xmlr.getNamespaceURI(i));
}
for (int i = 0, len = xmlr.getAttributeCount(); i < len; i++) {
String attUri = xmlr.getAttributeNamespace(i);
if (attUri != null) {
writer.writeAttribute(attUri, xmlr.getAttributeLocalName(i), xmlr.getAttributeValue(i));
} else {
writer.writeAttribute(xmlr.getAttributeLocalName(i), xmlr.getAttributeValue(i));
}
}
break;
case XMLEvent.END_ELEMENT:
writer.writeEndElement();
break;
case XMLEvent.SPACE:
case XMLEvent.CHARACTERS:
writer.writeCharacters(xmlr.getTextCharacters(), xmlr.getTextStart(), xmlr.getTextLength());
break;
case XMLEvent.PROCESSING_INSTRUCTION:
writer.writeProcessingInstruction(xmlr.getPITarget(), xmlr.getPIData());
break;
case XMLEvent.CDATA:
writer.writeCData(xmlr.getText());
break;
case XMLEvent.COMMENT:
writer.writeComment(xmlr.getText());
break;
case XMLEvent.ENTITY_REFERENCE:
writer.writeEntityRef(xmlr.getLocalName());
break;
case XMLEvent.START_DOCUMENT:
String encoding = xmlr.getCharacterEncodingScheme();
String version = xmlr.getVersion();
if (encoding != null && version != null) {
writer.writeStartDocument(encoding, version);
} else if (version != null) {
writer.writeStartDocument(xmlr.getVersion());
}
break;
case XMLEvent.END_DOCUMENT:
writer.writeEndDocument();
break;
case XMLEvent.DTD:
writer.writeDTD(xmlr.getText());
break;
}
}
它有效,但我不确定write()-method
. 那些开关盒真的有必要吗?
我也遇到了问题,将 ZIP-Elements 替换为
while (reader.hasNext()) {
write(reader, writer);
reader.next();
if (reader.getEventType() == XMLStreamReader.START_ELEMENT) {
String elementName = reader.getLocalName();
if (elementName.contains("ZIP")) {
writer.writeStartElement("newElem");
writer.writeAttribute("atr", "val");
writer.writeEndElement();
}
}
}
替换 XML 文件中的某些节点的最有效方法是什么?
解决方案
XSLT 有所谓的身份转换模式。
有用的链接:XSL 身份转换
下面的 XSLT 将按原样复制整个输入 XML,但 Zip 元素除外。找到 Zip 元素的那一刻,它将被新的所需标签替换。
您所要做的就是从您的Java 代码中调用XSLT 转换。
输入 XML
<?xml version="1.0" encoding="UTF-8"?>
<Company>
<Employee>
<FirstName>Tanmay</FirstName>
<LastName>Patil</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Bangalore</City>
<State>Karnataka</State>
<Zip>560212</Zip>
</Address>
</Employee>
</Company>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" encoding="utf-8"/>
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Zip">
<NewElem>Some value</NewElem>
</xsl:template>
</xsl:stylesheet>
输出 XML
<?xml version='1.0' encoding='utf-8' ?>
<Company>
<Employee>
<FirstName>Tanmay</FirstName>
<LastName>Patil</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Bangalore</City>
<State>Karnataka</State>
<NewElem>Some value</NewElem>
</Address>
</Employee>
</Company>
推荐阅读
- c# - 收集数据(从 frm1 调用一个收集器方法到 frm2)
- python - Python/Numpy - 新数组中简单线性回归的返回斜率
- youtube-data-api - GSuite API 凭据上的品牌 YouTube 频道出现 403 org_internal 错误
- java - 从字符串中删除自定义标签,然后格式化其内容
- sorting - Vuetify 使用什么比较器对数据表 String 列进行排序
- java - 找不到javac包
- tkinter - PIL 图像导入错误以及如何在 Tkinter 应用程序中显示图像
- r - 值很少的闪亮 R 滑块
- java - TCP 服务器客户端,客户端仅在服务器套接字关闭时打印传入字符串
- dart - 函数内的final关键字