【问题标题】:Java Replace words within xmlJava替换xml中的单词
【发布时间】:2016-09-02 18:56:34
【问题描述】:

我有以下xml

<some tag>
    <some_nested_tag attr="Hello"> Text </some_nested_tag>
    Hello world Hello Programming
</some tag>

从上面的xml中,我想替换出现的单词“Hello”,它们是标签内容的一部分,但不是标签属性的一部分。

我想要以下输出(用 HI 替换 Hello):

<some tag>
    <some_nested_tag attr="Hello"> Text </some_nested_tag>
    HI world HI Programming
</some tag>

我尝试了 java regex 和一些 DOM 解析器教程,但没有任何运气。我在这里发帖寻求帮助,因为我在我的项目中解决这个问题的时间有限。帮助将不胜感激。

【问题讨论】:

  • 正则表达式不是做到这一点的方法。更好地解析它并修改标签内容。

标签: java regex xml xml-parsing


【解决方案1】:

这可以通过使用消极的后视来完成。

试试这个正则表达式:

(?<!attr=")Hello

它将匹配前面没有attr=Hello

所以你可以试试这个:

str = str.replaceAll("(?<!attr=")Hello", "Hi");

也可以通过负前瞻来完成:

Hello(?!([^<]+)?>)

【讨论】:

  • 感谢您的回答,但它可以是任何属性名称,例如我放了'attr'
  • 用否定前瞻更新了答案。
  • 感谢它对我有用。我稍微更改了正则表达式,因为在我们的 xml 中,我们也有引号中的目标词,如“Hello”或关闭标签“>”之后的空格。这个我在我的代码中使用了 "(?!([^)\\b" + Word_to_be_replaced + "\\b"
【解决方案2】:
string.replaceAll("(?i)\\shello\\s", " HI ");

正则表达式解释:

\sHello\s

Options: Case insensitive

Match a single character that is a “whitespace character” (ASCII space, tab, line feed, carriage return, vertical tab, form feed) «\s»
Match the character string “Hello” literally (case insensitive) «Hello»
Match a single character that is a “whitespace character” (ASCII space, tab, line feed, carriage return, vertical tab, form feed) «\s»

 hi 

Insert the character string “ HI ” literally « HI »

Regex101 Demo

【讨论】:

    【解决方案3】:

    XSLT 是一种用于将 XML 文档转换为其他 XML 文档的语言。您可以匹配所有包含“Hello”的文本节点并替换这些特定节点的内容。

    在 Java 中使用 XSLT 的一个小例子:

    import javax.xml.transform.*;
    import javax.xml.transform.stream.StreamResult;
    import javax.xml.transform.stream.StreamSource;
    import java.io.File;
    import java.io.IOException;
    import java.net.URISyntaxException;
    
    public class TestMain {
        public static void main(String[] args) throws IOException, URISyntaxException, TransformerException {
            TransformerFactory factory = TransformerFactory.newInstance();
            Source xslt = new StreamSource(new File("transform.xslt"));
            Transformer transformer = factory.newTransformer(xslt);
    
            Source text = new StreamSource(new File("input.xml"));
            transformer.transform(text, new StreamResult(new File("output.xml")));
        }
    }
    

    有一个关于使用 XSLT 替换字符串的好问题 - 您可以在此处找到 XSLT 模板的示例: XSLT string replace

    【讨论】:

      【解决方案4】:

      这是一个使用 SAX 解析器的全功能示例。它适用于您的情况,对this example的改动很小

      实际替换发生在 MyCopyHandler#endElement() 和 MyCopyHandler#startElement() 中,XML 元素文本内容收集在 MyCopyHandler#characters() 中。还要注意缓冲区维护 - 在处理混合元素内容(文本和子元素)时很重要

      我知道 XSLT 解决方案也是可能的,但它不是那么便携。

      public class XMLReplace {
      
          /**
           * @param args
           * @throws SAXException
           * @throws ParserConfigurationException
           */
          public static void main(String[] args) throws Exception {
      
              final String str = "<root> Hello <nested attr='Hello'> Text </nested>  Hello world Hello Programming </root>";
      
              SAXParserFactory spf = SAXParserFactory.newInstance();
              SAXParser parser = spf.newSAXParser();
              XMLReader reader = parser.getXMLReader();
              reader.setErrorHandler(new MyErrorHandler());
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              PrintWriter out = new PrintWriter(baos);
              MyCopyHandler duper = new MyCopyHandler(out);
              reader.setContentHandler(duper);
              InputSource is = new InputSource(new StringReader(str));
              reader.parse(is);
              out.close();
              System.out.println(baos);
          }
      
      }
      
      class MyCopyHandler implements ContentHandler {
          private boolean namespaceBegin = false;
      
          private String currentNamespace;
      
          private String currentNamespaceUri;
      
          private Locator locator;
      
          private final PrintWriter out;
      
          private final StringBuilder buffer = new StringBuilder();
      
          public MyCopyHandler(PrintWriter out) {
              this.out = out;
          }
      
          public void setDocumentLocator(Locator locator) {
              this.locator = locator;
          }
      
          public void startDocument() {
          }
      
          public void endDocument() {
          }
      
          public void startPrefixMapping(String prefix, String uri) {
              namespaceBegin = true;
              currentNamespace = prefix;
              currentNamespaceUri = uri;
          }
      
          public void endPrefixMapping(String prefix) {
          }
      
          public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
      
              // Flush buffer - needed in case of mixed content (text + elements)
              out.print(buffer.toString().replaceAll("Hello", "HI"));
              // Prepare to collect element text content
              this.buffer.setLength(0);
      
              out.print("<" + qName);
              if (namespaceBegin) {
                  out.print(" xmlns:" + currentNamespace + "=\"" + currentNamespaceUri + "\"");
                  namespaceBegin = false;
              }
              for (int i = 0; i < atts.getLength(); i++) {
                  out.print(" " + atts.getQName(i) + "=\"" + atts.getValue(i) + "\"");
              }
              out.print(">");
          }
      
          public void endElement(String namespaceURI, String localName, String qName) {
              // Process text content
              out.print(buffer.toString().replaceAll("Hello", "HI"));
              out.print("</" + qName + ">");
              // Reset buffer
              buffer.setLength(0);
          }
      
          public void characters(char[] ch, int start, int length) {
              // Store chunk of text - parser is allowed to provide text content in chunks for performance reasons
              buffer.append(Arrays.copyOfRange(ch, start, start + length));
          }
      
          public void ignorableWhitespace(char[] ch, int start, int length) {
              for (int i = start; i < start + length; i++)
                  out.print(ch[i]);
          }
      
          public void processingInstruction(String target, String data) {
              out.print("<?" + target + " " + data + "?>");
          }
      
          public void skippedEntity(String name) {
              out.print("&" + name + ";");
          }
      }
      
      class MyErrorHandler implements ErrorHandler {
          public void warning(SAXParseException e) throws SAXException {
              show("Warning", e);
              throw (e);
          }
      
          public void error(SAXParseException e) throws SAXException {
              show("Error", e);
              throw (e);
          }
      
          public void fatalError(SAXParseException e) throws SAXException {
              show("Fatal Error", e);
              throw (e);
          }
      
          private void show(String type, SAXParseException e) {
              System.out.println(type + ": " + e.getMessage());
              System.out.println("Line " + e.getLineNumber() + " Column " + e.getColumnNumber());
              System.out.println("System ID: " + e.getSystemId());
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-13
        • 1970-01-01
        • 2021-12-29
        • 2015-03-02
        • 1970-01-01
        相关资源
        最近更新 更多