【问题标题】:What is the best way to split a string, when the prefix delimiters and the suffix delimiters are different?当前缀分隔符和后缀分隔符不同时,拆分字符串的最佳方法是什么?
【发布时间】:2014-02-11 12:59:18
【问题描述】:

在Java中,当每个块开头的分隔符与每个块末尾的分隔符不同时,将字符串拆分为块数组的最佳方法是什么?

例如,假设我有String string = "abc 1234 xyz abc 5678 xyz"

我想应用某种复杂的split 以获得{"1234","5678"}

首先想到的是:

String[] parts = string.split("abc");
for (String part : parts)
{
    String[] blocks = part.split("xyz");
    String data = blocks[0];
    // Do some stuff with the 'data' string
}

有没有更简单/更清洁/更有效的方法?

我的目的(您可能已经猜到了)是解析 XML 文档。

我想将给定的 XML 字符串拆分为给定标记的内部 XML 块。

例如:

String xml = "<tag>ABC</tag>White Spaces Only<tag>XYZ</tag>";
String[] blocks = Split(xml,"<tag>","</tag>"); // should be {"ABC","XYZ"}

您将如何实现String[] Split(String str,String prefix,String suffix)

谢谢

【问题讨论】:

  • 您可以使用正则表达式,但如果您的表达式比您的示例更复杂,您可能应该使用 xml 解析器。
  • 您将无法正确处理&lt;tag&gt;&lt;tag&gt;foo bar&lt;/tag&gt;&lt;/tag&gt;
  • @JoshuaTaylor 是对的。在使用诸如 XML 之类的重要语法时,您应该使用某人已经编写的软件。肯定有一个学习曲线,但你花在学习上的时间比你花在寻找“奇怪”案例(如 cmets、嵌套标签和转义终止符)上​​的时间要少得多。

标签: java xml regex string-split


【解决方案1】:

最好的办法是使用专用的 XML 解析器之一。 请参阅 this discussion 了解 Java 的最佳 XML 解析器。

我发现这个DOM XML parser example 简单而好。

【讨论】:

    【解决方案2】:

    恕我直言,最好的解决方案是解析 XML 文件,这不是单行的……

    here

    这里有来自另一个关于 SO 的问题的示例代码来解析文档,然后使用 XPATH 移动:

    String xml = "<resp><status>good</status><msg>hi</msg></resp>";
    
    InputSource source = new InputSource(new StringReader(xml));
    
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document document = db.parse(source);
    
    XPathFactory xpathFactory = XPathFactory.newInstance();
    XPath xpath = xpathFactory.newXPath();
    
    String msg = xpath.evaluate("/resp/msg", document);
    String status = xpath.evaluate("/resp/status", document);
    
    System.out.println("msg=" + msg + ";" + "status=" + status);
    

    这篇帖子的完整主题here

    【讨论】:

      【解决方案3】:

      你可以为这种类型的字符串写一个正则表达式……

      \s*((^abc)|(xyz\s*abc)|(\s*xyz$))\s* 这样开头的abc 或结尾的xyz 或中间的abc xyz 怎么样(以一些空格为模)?这在开始时会产生一个空值,但除此之外,它似乎会做你想做的事。

      import java.util.Arrays;
      
      public class RegexDelimitersExample {
          public static void main(String[] args) {
              final String string = "abc 1234 xyz abc 5678 xyz";
              final String pattern = "\\s*((^abc)|(xyz\\s*abc)|(\\s*xyz$))\\s*";
              final String[] parts_ = string.split( pattern );
              // parts_[0] is "", because there's nothing before ^abc,
              // so a copy of the rest of the array is what we want.
              final String[] parts = Arrays.copyOfRange( parts_, 1, parts_.length );
              System.out.println( Arrays.deepToString( parts ));
          }
      }
      
      [1234, 5678]
      

      根据您希望如何处理空格,您可以根据需要进行调整。例如,

      \s*((^abc)|(xyz\s*abc)|(\s*xyz$))\s*     # original
      (^abc\s*)|(\s*xyz\s*abc\s*)|(\s*xyz$)    # no spaces on outside
      ...                                      # ...
      

      …但你不应该将它用于 XML。

      不过,正如我在 cmets 中所指出的,这将适用于拆分具有这些定界符的 非嵌套 字符串。您将无法使用正则表达式处理嵌套案例(例如,abc abc 12345 xyz xyz),因此您将无法处理一般 XML(这似乎是您的意图)。如果您确实需要解析 XML,请使用专为 XML 设计的工具(例如解析器、XPath 查询等)。

      【讨论】:

        【解决方案4】:

        这里不要使用正则表达式。但是您也不必进行成熟的 XML 解析。使用XPath。在您的示例中搜索的表达式是

        //tag/text()
        

        需要的代码是:

        import org.w3c.dom.NodeList;
        import org.xml.sax.*;
        import javax.xml.xpath.*;
        
        public class Test {
        
            public static void main(String[] args) throws Exception {
        
                InputSource ins = new InputSource("c:/users/ndh/hellos.xml");
                XPath xpath = XPathFactory.newInstance().newXPath();
                NodeList list = (NodeList)xpath.evaluate("//bar/text()", ins, XPathConstants.NODESET);
                for (int i = 0; i < list.getLength(); i++) {
                    System.out.println(list.item(i).getNodeValue());
                }
                
            }
        }
        

        我的示例 xml 文件在哪里

        <?xml version="1.0"?>
        <foo>
            <bar>hello</bar>
            <bar>ohayoo</bar>
            <bar>hola</bar>
        </foo>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-10-02
          • 2017-04-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-19
          相关资源
          最近更新 更多