Java中如何移除XML命名空间(适配SAX/JAXB项目场景)
Java移除XML命名空间实现方案(适配SAX/JAXB环境)
方案1:SAX过滤器实现(推荐,无额外依赖)
你项目已引入SAX组件,直接用SAX过滤器对XML流做预处理即可,核心逻辑是拦截元素命名空间相关事件,清除命名空间前缀和URI,仅保留元素本地名:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.XMLFilterImpl; public class NamespaceFilter extends XMLFilterImpl { // 忽略命名空间前缀映射事件 @Override public void startPrefixMapping(String prefix, String uri) throws SAXException { // 不向下传递命名空间映射 } @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { // 清除命名空间URI,取本地名作为元素名 super.startElement("", localName, localName, atts); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement("", localName, localName); } }
配套转换工具类代码:
import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import java.io.StringReader; import java.io.StringWriter; public class XmlNamespaceRemover { public static String removeNamespace(String inputXml) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); XMLReader xmlReader = parser.getXMLReader(); // 挂载自定义命名空间过滤器 NamespaceFilter filter = new NamespaceFilter(); filter.setParent(xmlReader); // 转换输出无命名空间XML Transformer transformer = TransformerFactory.newInstance().newTransformer(); StringWriter writer = new StringWriter(); transformer.transform(new SAXSource(filter, new InputSource(new StringReader(inputXml))), new StreamResult(writer)); return writer.toString(); } }
测试调用示例:
public class Test { public static void main(String[] args) throws Exception { String inputXml = "<ns2:client xmlns:ns2=\"http://my-org/schemas\" instance=\"1\">\n" + " <ns2:dob>1969-01-01T00:00:00</ns2:dob>\n" + " <ns2:firstname>Anna</ns2:firstname>\n" + " <ns2:married>false</ns2:married>\n" + " <ns2:gender>Female</ns2:gender>\n" + " <ns2:surname>Smith</ns2:surname>\n" + " <ns2:title>Miss</ns2:title>\n" + "</ns2:client>"; String outputXml = XmlNamespaceRemover.removeNamespace(inputXml); System.out.println(outputXml); } }
运行后输出结果和你给出的预期格式完全一致。
方案2:对接JAXB场景
如果需要直接用处理后的XML做JAXB反序列化,不需要生成中间字符串,直接把SAX过滤器包装的输入源传给JAXB的Unmarshaller即可,性能更高:
import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import javax.xml.transform.sax.SAXSource; // 替换为你自己的JAXB实体类 import com.example.Client; // 调用示例 SAXSource source = new SAXSource(filter, new InputSource(new StringReader(inputXml))); JAXBContext context = JAXBContext.newInstance(Client.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Client client = (Client) unmarshaller.unmarshal(source);
该实现完全适配你现有JAXB组件的使用流程。
注意事项
- 默认实现会保留无命名空间的属性,你示例中的
instance属性会正常保留,如果需要处理带命名空间的属性,只需要在startElement方法中遍历Attributes做对应修改即可 - SAXParserFactory不需要额外开启命名空间感知,默认配置即可正常运行
内容的提问来源于stack exchange,提问作者christosonjava
相关产品推荐
相关产品推荐

