【问题标题】:How do I extract child element from XML to a string in Java?如何从 XML 中提取子元素到 Java 中的字符串?
【发布时间】:2009-03-10 20:05:15
【问题描述】:

如果我有一个类似的 XML 文档

<root>   
   <element1>
        <child attr1="blah">
           <child2>blahblah</child2>
        <child>   
   </element1> 
</root>

我想获得一个带有第一个子元素的 XML 字符串。我的输出字符串是

<element1>
    <child attr1="blah">
       <child2>blahblah</child2>
    <child>
</element1>

有很多方法,想看看一些想法。我一直在尝试为此使用 Java XML API,但不清楚是否有一种好方法可以做到这一点。

谢谢

【问题讨论】:

    标签: java xml


    【解决方案1】:

    您说得对,使用标准 XML API 并没有什么好方法 - 这是一个示例(可能存在错误;它可以运行,但我很久以前就写过了)。

    import javax.xml.*;
    import javax.xml.parsers.*;
    import javax.xml.transform.*;
    import javax.xml.transform.dom.*;
    import javax.xml.transform.stream.*;
    import org.w3c.dom.*;
    import java.io.*;
    
    public class Proc
    {
        public static void main(String[] args) throws Exception
        {
            //Parse the input document
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new File("in.xml"));
    
            //Set up the transformer to write the output string
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer();
            transformer.setOutputProperty("indent", "yes");
            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
    
            //Find the first child node - this could be done with xpath as well
            NodeList nl = doc.getDocumentElement().getChildNodes();
            DOMSource source = null;
            for(int x = 0;x < nl.getLength();x++)
            {
                Node e = nl.item(x);
                if(e instanceof Element)
                {
                    source = new DOMSource(e);
                    break;
                }
            }
    
            //Do the transformation and output
            transformer.transform(source, result);
            System.out.println(sw.toString());
        }
    }
    

    看起来你可以通过使用 doc.getDocumentElement().getFirstChild() 来获得第一个子元素,但问题是如果根元素和子元素之间有任何空格,则会创建一个文本树中的节点,您将获得该节点而不是实际的元素节点。该程序的输出是:

    D:\home\tmp\xml>java Proc
    <?xml version="1.0" encoding="UTF-8"?>
    <element1>
            <child attr1="blah">
               <child2>blahblah</child2>
           </child>
       </element1>
    

    我认为如果您不需要 xml 版本字符串,您可以取消它,但我不确定。如果可能的话,我可能会尝试使用第三方 XML 库。

    【讨论】:

      【解决方案2】:

      因为这是谷歌的最佳答案,对于那些只想要基本知识的人:

          public static String serializeXml(Element element) throws Exception
      {
          ByteArrayOutputStream buffer = new ByteArrayOutputStream();
          StreamResult result = new StreamResult(buffer);
      
          DOMSource source = new DOMSource(element);
          TransformerFactory.newInstance().newTransformer().transform(source, result);
      
          return new String(buffer.toByteArray());
      }
      

      我用这个来调试,这很可能是你需要的

      【讨论】:

      • 你知道如何防止transformer添加吗?
      • @jophde 通过将转换器提取到变量并在其上调用 setOutputProperty(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes")
      【解决方案3】:

      我会推荐JDOM。它是一个 Java XML 库,它使处理 XML 比标准 W3C 方法更容易。

      【讨论】:

        【解决方案4】:

        XMLBeans 是一个易于使用(一旦掌握了它)的工具来处理 XML,而不必处理解析的烦恼。

        它要求您有 XML 文件的架构,但它还提供了一个工具来从现有 XML 文件生成架构(取决于您的需要,生成的可能很好)。

        【讨论】:

          【解决方案5】:
          public String getXML(String xmlContent, String tagName){
          
              String startTag = "<"+ tagName + ">";
              String endTag = "</"+ tagName + ">";
              int startposition = xmlContent.indexOf(startTag);
              int endposition = xmlContent.indexOf(endTag, startposition);
              if (startposition == -1){
                  return "ddd";
              }
              startposition += startTag.length();
              if(endposition == -1){ 
                  return "eee";
              }
              return xmlContent.substring(startposition, endposition);
          }
          

          将您的 xml 作为字符串传递给此方法,在您的情况下,将“元素”作为参数标记名传递。

          【讨论】:

            【解决方案6】:

            如果您的 xml 有支持它的架构,您可以使用 xmlbeans 或 JAXB 生成帮助您编组/解组 xml 的 pojo 对象。

            http://xmlbeans.apache.org/ https://jaxb.dev.java.net/

            【讨论】:

              【解决方案7】:

              由于问题实际上是关于另一个字符串中第一次出现的字符串,我会使用 String 类方法,而不是 XML 解析器:

              public static String getElementAsString(String xml, String tagName){
                  int beginIndex = xml.indexOf("<" + tagName);
                  int endIndex = xml.indexOf("</" + tagName, beginIndex) + tagName.length() + 3;
                  return xml.substring(beginIndex, endIndex);
              }
              

              【讨论】:

                【解决方案8】:

                您可以使用以下函数通过传递正确的 xpath 表达式将 xml 块提取为字符串,

                    private static String nodeToString(Node node) throws TransformerException
                {
                    StringWriter buf = new StringWriter();
                    Transformer xform = TransformerFactory.newInstance().newTransformer();
                    xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
                    xform.transform(new DOMSource(node), new StreamResult(buf));
                    return(buf.toString());
                }
                
                    public static void main(String[] args) throws Exception
                {
                        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                        Document doc = dBuilder.parse(inputFile);
                
                        XPath xPath = XPathFactory.newInstance().newXPath();
                        Node result = (Node)xPath.evaluate("A/B/C", doc, XPathConstants.NODE); //"A/B[id = '1']" //"//*[@type='t1']"
                
                        System.out.println(nodeToString(result));
                
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-12-10
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-08-28
                  • 2019-03-04
                  相关资源
                  最近更新 更多