如何在Java中修改XML文档并将其作为字符串返回?

huangapple go评论71阅读模式
英文:

How to modify an xml document and return it as a string in java?

问题

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.filter.ElementFilter;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;

public String removeIds(String xmlString) {
    Document doc = null;
    SAXBuilder saxBuilder = new SAXBuilder();

    try {
        doc = saxBuilder.build(new StringReader(xmlString));
    } catch (JDOMException je) {
        je.printStackTrace();
    } catch (IOException ie) {
        ie.printStackTrace();
    }

    Element rootNode = doc.getRootElement();
    Iterator<Element> rootChildren = rootNode.getDescendants(new ElementFilter("Person"));

    for (Element person : rootChildren) {
        for (Element identity : person.getChildren("Identity")) {
            identity.removeChildren("id");
        }
    }

    try {
        XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
        StringWriter writer = new StringWriter();
        xmlOutputter.output(doc, writer);
        String output = writer.getBuffer().toString();
        return output;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

Note: The provided code snippet was modified to correct certain errors and to make it more functional. The provided code should be used in the context of a Java project with the JDOM library imported and configured correctly. Make sure you have the necessary libraries and dependencies set up for your project before using this code.

英文:

I have this string containing my request xml. I want to delete below "id" tags from this string if they exist and return it back. Removing "Identity" completely will also work, if that can be done.

To be deleted :
 &lt;Identity&gt;
&lt;id extension=&quot;7865232&quot; aan = &quot;BUH&quot;/&gt;
&lt;code/&gt;
&lt;/Identity&gt;
&lt;Identity&gt;
&lt;id extension=&quot;88769032&quot; aan = &quot;DIH&quot;/&gt;
&lt;code/&gt;
&lt;/Identity&gt;

String XMLString= &quot;&lt;request version =&quot;1.0&quot;&gt;
&lt;minMatch&gt;
&lt;val&gt;100&lt;/val&gt;
&lt;/minMatch&gt;
&lt;paramList&gt;
&lt;payLoad display = &quot;Full&quot; type=&quot;F&quot;&gt;
&lt;/payLoad&gt;
&lt;IQC code = &quot;2&quot;&gt;
&lt;/IQC&gt;
&lt;Control display=&quot;Default&quot; type = &quot;D&quot;&gt;
&lt;/Control&gt;
&lt;member&gt;
&lt;memCode code = &quot;Active&quot;
&lt;/memCode&gt;
&lt;id extension=&quot;12345&quot; aan=&quot;ACC&quot;&gt;&lt;/id&gt;
&lt;id extension=&quot;54321&quot; aan=&quot;REQ&quot;&gt;&lt;/id&gt;
&lt;id extension=&quot;554376&quot; aan=&quot;PDR&quot;&gt;&lt;/id&gt;
&lt;id extension=&quot;66321&quot; aan=&quot;NJQ&quot;&gt;&lt;/id&gt;
&lt;addr use = &quot;H&quot;&gt;
&lt;streetLine&gt;123&lt;/streetLine&gt;
&lt;city&gt;POLIS&lt;/city&gt;
&lt;state&gt;NY&lt;/state&gt;
&lt;postalCode&gt;44321&lt;/postalCode&gt;
&lt;/addr&gt;
&lt;telecom value = &quot;5543213&quot;&gt;
&lt;/telecom&gt;
&lt;Person&gt;
&lt;name&gt;
&lt;given&gt;JOHN&lt;/given&gt;
&lt;family&gt;BILL&lt;/family&gt;
&lt;/name&gt;
&lt;GenderCode code =&quot;M&quot; display=&quot;Male&quot;&gt;
&lt;/GenderCode&gt;
&lt;birthime vaue=&quot;19651002&quot;&gt;
&lt;/birthime&gt;
&lt;Identity&gt;
&lt;id extensio=&quot;7865232&quot; aan = &quot;BUH&quot;/&gt;
&lt;code/&gt;
&lt;/Identity&gt;
&lt;Identity&gt;
&lt;id extensio=&quot;88769032&quot; aan = &quot;DIH&quot;/&gt;
&lt;code/&gt;
&lt;/Identity&gt;
&lt;/Person&gt;
&lt;/member&gt;
----
---
&lt;/request&gt;&quot;

I am using below code to achieve the same but it's not working and giving me The constructor DOMSource(Document) is undefined. I tired converting document into a byte Array but that's also not working.Is there any way i can simply do this in Java 1.8. Any other approach is also welcome.
Please suggest.Thank you!

public void removeIds(String xmlString){

Document doc = null;
SAXBuilder saxbuilder = new SAXBuilder();

try{
doc = saxbuilder.build(new StringReader(xmlString));
}catch(JDOMException je){
je.printStackTrace();
}catch(IOException ie){
ie.printStackTrace();
}

Element rootNode = doc.getRootElement();
IteratorIterable&lt;Element&gt; rootChildren=rootNode.getDescendants(new ElementFilter(&quot;Person&quot;));

for(Element Person:rootChildren){
 for(Element Identity:Person.getChildren(&quot;Identity&quot;)){

((Element) doc.getRootElement.getDescendants(new ElementFilter(&quot;Identity&quot;))).removeChild(&quot;id&quot;);

  }
}

try{

TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer;
        
            transformer = tf.newTransformer();

            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, &quot;yes&quot;);

            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(doc), new StreamResult(writer));
            String output = writer.getBuffer().toString();
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        
       
    }

答案1

得分: 2

由于您已经调用了一个转换,所以在XSLT中完成所有工作要比在低级DOM操作中瞎弄要简单得多。

如果您使用XSLT 3.0(Saxon),样式表如下:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:mode on-no-match="shallow-copy"/>
  <xsl:output indent="yes" encoding="utf-8"/>
  <xsl:template match="id"/>
</xsl:transform>

您可以将输入提供给此转换,方法是 new StreamSource(new StringReader(xmlString)) — 无需首先构建DOM。

这也可以在XSLT 1.0中完成(例如,使用捆绑在JDK中的Xalan),但会有点冗长。

英文:

Since you're invoking a transformation anyway, it's much simpler to do all the work in XSLT rather than fiddle about with low-level DOM manipulation.

If you use XSLT 3.0 (Saxon) then the stylesheet is simply

&lt;xsl:transform version=&quot;3.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
  &lt;xsl:mode on-no-match=&quot;shallow-copy&quot;/&gt;
  &lt;xsl:output indent=&quot;yes&quot; encoding=&quot;utf-8&quot;/&gt;
  &lt;xsl:template match=&quot;id&quot;/&gt;
&lt;/xsl:transform&gt;

You can supply the input to this transformation as new StreamSource(new StringReader(xmlString)) -- there's no need to construct a DOM first.

It can be done in XSLT 1.0 too (i.e. with Xalan, which comes bundled with the JDK), but is a bit more verbose.

答案2

得分: 1

以下是使用XPath API的解决方案。在这个例子中,所有位于元素“Identity”内部的元素“id”都被移除(XPath表达式“//Identity/id”)。如果您想要移除所有的id元素,请将表达式更改为“//id”。

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

// XML序列化的函数
public static String serialize(Document document) {
    removeWhitespaces(document.getDocumentElement());
    try (StringWriter writer = new StringWriter()) {
        StreamResult result = new StreamResult(writer);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.transform(new DOMSource(document), result);
        return writer.toString();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

// 用于去除空白的辅助函数
public static void removeWhitespaces(Element element) {
    NodeList children = element.getChildNodes();
    for (int i = children.getLength() - 1; i >= 0; i--) {
        Node child = children.item(i);
        if (child instanceof Text && ((Text) child).getData().trim().isEmpty()) {
            element.removeChild(child);
        } else if (child instanceof Element) {
            removeWhitespaces((Element) child);
        }
    }
}

// 主要代码

// 解析XML
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(xml)));

// 查找id元素
XPathExpression xpath = XPathFactory.newInstance().newXPath().compile("//Identity/id");
NodeList nodes = (NodeList) xpath.evaluate(doc, XPathConstants.NODESET);

// 移除找到的元素
for (int i = 0; i < nodes.getLength(); i++) {
    Node node = nodes.item(i);
    node.getParentNode().removeChild(node);
}

// 序列化并输出文档
String result = serialize(doc);
System.out.println(result);
英文:

Here is solution using XPath API. In this example all elements "id" inside elements "Identity" are removed (XPath expression "//Identity/id"). If you want to remove all id elements, change it to "//id".

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
// function for XML serialization
public static String serialize(Document document) {
removeWhitespaces(document.getDocumentElement());
try (StringWriter writer = new StringWriter()) {
StreamResult result = new StreamResult(writer);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, &quot;xml&quot;);
transformer.setOutputProperty(OutputKeys.INDENT, &quot;yes&quot;);
transformer.setOutputProperty(&quot;{http://xml.apache.org/xslt}indent-amount&quot;, &quot;4&quot;);
transformer.setOutputProperty(OutputKeys.ENCODING, &quot;UTF-8&quot;);
transformer.transform(new DOMSource(document), result);
return writer.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// helper function for stripping whitespaces
public static void removeWhitespaces(Element element) {
NodeList children = element.getChildNodes();
for (int i = children.getLength() - 1; i &gt;= 0; i--) {
Node child = children.item(i);
if (child instanceof Text
&amp;&amp; ((Text) child).getData().trim().isEmpty()) {
element.removeChild(child);
} else if (child instanceof Element) {
removeWhitespaces((Element) child);
}
}
}

Main code:

    // parse XML
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(xml)));
// find id elements
XPathExpression xpath = XPathFactory.newInstance().newXPath().compile(&quot;//Identity/id&quot;);
NodeList nodes = (NodeList)xpath.evaluate(doc, XPathConstants.NODESET);
// remove found elements
for(int i = 0; i &lt; nodes.getLength(); i ++) {
Node node = nodes.item(i);
node.getParentNode().removeChild(node);
}
// serialize and output document
String result = serialize(doc);
System.out.println(result);

huangapple
  • 本文由 发表于 2020年10月5日 20:23:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/64208552.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定