【问题标题】:Replacing a parent XML tag if contains a string using regex如果包含使用正则表达式的字符串,则替换父 XML 标记
【发布时间】:2015-04-15 08:52:31
【问题描述】:

我有以下 XML:

<customer>
   <name>Customer name</name>
   <address>
      <postalcode>94510</postalcode>
      <town>Green Bay</town>
   </address>
   <phone>0645878787</phone>
</customer>

我想只使用正则表达式,用空字符串替换整个&lt;address&gt;..&lt;/address&gt; 标签如果邮政编码是94510

我有

String s = "<the xml above here/>"
s = s.replace(source, target);

我只能控制“源”和“目标”。有没有正则表达式可以解决这个问题?

谢谢

【问题讨论】:

  • 正则表达式不是正确的工具,因为 XML 不是常规语言。 Java 有 XML 处理工具;你为什么不想使用这些?
  • 您可以在这里找到很多选项:tutorialspoint.com/java_xml/java_xml_parsers.htm。你完全确定你不能使用 XML 解析器,而只需要一个正则表达式吗?正则表达式是(?s)&lt;address&gt;.*?&lt;postalcode&gt;94510&lt;/postalcode&gt;.*?&lt;/address&gt;\\s*,替换字符串是''。但是,如果您的 XML 格式不正确,您可能会得到意想不到的结果。
  • 请注意,replace 接受常规字符串,replaceAll 接受正则表达式。

标签: java regex xml replace


【解决方案1】:

在没有外部库的情况下,我能看到的最直接的方法是使用 XPath 表达式来选择应该删除的节点,然后删除它们。这在 Java 中相当冗长,但并不十分复杂:

import java.io.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import org.w3c.dom.*;

public class Foo {
  // Error handling should be done, but I can't know what you want to happen
  // in case of broken XML.
  public static void main(String[] args) throws Exception {
    String xml =
        "<customer>\n"
      + "   <name>Customer name</name>\n"
      + "   <address>\n"
      + "      <postalcode>94510</postalcode>\n"
      + "      <town>Green Bay</town>\n"
      + "   </address>\n"
      + "   <phone>0645878787</phone>\n"
      + "</customer>";

    // XPath expression: It selects all address nodes under /customer
    // that have a postalcode child whose text is 94510
    String selection = "/customer/address[postalcode=94510]";

    // Lots of fluff -- the XML API is full of factories; don't mind them.
    // What all this does is to parse the document from the string.
    InputStream     source   = new ByteArrayInputStream(xml.getBytes());
    Document        document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(source);

    // Create a list of nodes that match our XPath expression
    XPathExpression xpath    = XPathFactory.newInstance().newXPath().compile(selection);
    NodeList        nodes    = (NodeList) xpath.evaluate(document, XPathConstants.NODESET);

    // Remove all those nodes from the document
    for(int i = 0; i < nodes.getLength(); ++i) {
      Node n = nodes.item(i);
      n.getParentNode().removeChild(n);
    }

    // And finally print the document back into a string.
    StringWriter writer = new StringWriter();
    Transformer  tform  = TransformerFactory.newInstance().newTransformer();

    tform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    tform.transform(new DOMSource(document), new StreamResult(writer));

    // This is our result.
    String processed_xml = writer.getBuffer().toString();

    System.out.println(processed_xml);
  }
}

【讨论】:

    【解决方案2】:

    如前所述,请不要使用正则来处理 XML。以下是您应该采取的方法(代码改编自herehere)。:

    String str = "<customer>\n" +
                            "   <name>Customer name</name>\n" +
                            "   <address>\n" +
                            "      <postalcode>94510</postalcode>\n" +
                            "      <town>Green Bay</town>\n" +
                            "   </address>\n" +
                            "   <phone>0645878787</phone>\n" +
                            "</customer>";
    ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes());
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(bais);
    
    //optional, but recommended
    //read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
    doc.getDocumentElement().normalize();
    
    System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
    
    NodeList nList = doc.getElementsByTagName("address");
        for(int i = 0; i < nList.getLength(); i++)
        {         
            NodeList children = nList.item(i).getChildNodes();
            for(int j = 0; j < children.getLength(); j++)
            {
                Node current = children.item(j);
                if((current.getNodeName().equals("postalcode")) && (current.getTextContent().equals("94510")))
                {
                    current.getParentNode().getParentNode().removeChild(nList.item(i));                    
                }
            }            
        }
    
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StreamResult result = new StreamResult(new StringWriter());
        DOMSource source = new DOMSource(doc);
        transformer.transform(source, result);
    
        String xmlString = result.getWriter().toString();
        System.out.println(xmlString);
    

    产量:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <customer>
       <name>Customer name</name>
    
       <phone>0645878787</phone>
    </customer>
    

    如果你真的,真的必须使用正则表达式,看看下面:

    String str = "<customer>\n" +
                            "   <name>Customer name</name>\n" +
                            "   <address>\n" +
                            "      <postalcode>94510</postalcode>\n" +
                            "      <town>Green Bay</town>\n" +
                            "   </address>\n" +
                            "   <phone>0645878787</phone>\n" +
                            "</customer>";
    
        System.out.println(str.replaceAll("(?s)<address>.+?<postalcode>94510</postalcode>.+?</address>.+?<phone>", "<phone>"));
    

    产量:

    <customer>
       <name>Customer name</name>
       <phone>0645878787</phone>
    </customer>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 1970-01-01
      • 2015-11-30
      • 2015-02-27
      • 1970-01-01
      相关资源
      最近更新 更多