【问题标题】:How to avoid encoding of <,>,& with Document.createTextNode如何避免使用 Document.createTextNode 对 <、> 和 & 进行编码
【发布时间】:2012-09-21 06:11:13
【问题描述】:
class XMLencode 
{
  public static void main(String[] args) 
  {
    try{

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = factory.newDocumentBuilder();
    Document doc = docBuilder.newDocument();
    Element root = doc.createElement("roseindia");
       doc.appendChild(root);
    Text elmnt=doc.createTextNode("<data>sun</data><abcdefg/><end/>");
       root.appendChild(elmnt);
     TransformerFactory tranFactory = TransformerFactory.newInstance(); 
    Transformer aTransformer = tranFactory.newTransformer(); 
    Source src = new DOMSource(doc); 
    Result dest = new StreamResult(System.out); 
    aTransformer.transform(src, dest); 

    }catch(Exception e){
     System.out.println(e.getMessage());
         }
     }
}

这是我上面的一段代码。 生成的输出是这样的

<?xml version="1.0" encoding="UTF-8" standalone="no"?><roseindia>&lt;data&gt;sun&lt;/data&gt;&lt;abcdefg/&gt;&lt;end/&gt;</roseindia>

我不希望对标签进行编码。我需要这种方式的输出。

<?xml version="1.0" encoding="UTF-8" standalone="no"?><roseindia><data>sun</data><abcdefg/><end/></roseindia>

请帮帮我。

谢谢, 磨难

【问题讨论】:

    标签: java xml


    【解决方案1】:

    简答

    您可以利用 XML 中的 CDATA 机制来防止字符被转义。下面是一个 DOM 代码示例:

    doc.createCDATASection("<foo/>");
    

    内容将是:

    <![CDATA[<foo/>]]>
    

    长答案

    以下是使用 DOM API 来利用 CDATA 部分的完整示例。

    package forum12525152;
    
    import javax.xml.parsers.*;
    import javax.xml.transform.*;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import org.w3c.dom.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.newDocument();
    
            Element rootElement = document.createElement("root");
            document.appendChild(rootElement);
    
            // Create Element with a Text Node
            Element fooElement = document.createElement("foo");
            fooElement.setTextContent("<foo/>");
            rootElement.appendChild(fooElement);
    
            // Create Element with a CDATA Section
            Element barElement = document.createElement("bar");
            CDATASection cdata = document.createCDATASection("<bar/>");
            barElement.appendChild(cdata);
            rootElement.appendChild(barElement);
    
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer t = tf.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(System.out);
            t.transform(source, result);
        }
    
    }
    

    输出

    请注意foobar 元素的区别,即使它们具有相似的内容。我已经对运行演示代码的结果进行了格式化,使其更具可读性:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <root>
        <foo>&lt;foo/&gt;</foo>
        <bar><![CDATA[<bar/>]]></bar>
    </root>
    

    【讨论】:

      【解决方案2】:

      不要这样写doc.createTextNode("&lt;data&gt;sun&lt;/data&gt;&lt;abcdefg/&gt;&lt;end/&gt;");

      您应该创建每个元素。

      import javax.xml.parsers.*;
      import javax.xml.transform.*;
      import javax.xml.transform.dom.*;
      import javax.xml.transform.stream.*;
      import org.w3c.dom.*;
      class XMLencode {
          public static void main(String[] args) {
              try {
      
                  DocumentBuilderFactory factory = DocumentBuilderFactory
                          .newInstance();
                  DocumentBuilder docBuilder = factory.newDocumentBuilder();
                  Document doc = docBuilder.newDocument();
                  Element root = doc.createElement("roseindia");
                  doc.appendChild(root);
      
                  Element data = doc.createElement("data");
                  root.appendChild(data);
                  Text elemnt = doc.createTextNode("sun");
                  data.appendChild(elemnt);
                  Element data1 = doc.createElement("abcdefg");
                  root.appendChild(data1);
      
                  //Text elmnt = doc.createTextNode("<data>sun</data><abcdefg/><end/>");
                  //root.appendChild(elmnt);
      
                  TransformerFactory tranFactory = TransformerFactory.newInstance();
                  Transformer aTransformer = tranFactory.newTransformer();
                  Source src = new DOMSource(doc);
                  Result dest = new StreamResult(System.out);
                  aTransformer.transform(src, dest);
      
              } catch (Exception e) {
                  System.out.println(e.getMessage());
              }
          }
      }
      

      【讨论】:

      • 感谢您的回复,但我们获得的 xml 数据是动态的,因此我们无法单独构建每个元素并附加到根元素。请建议任何替代方法...谢谢
      【解决方案3】:

      您可以使用 doc.createTextNode 并对转义字符使用解决方法(长)。

      SOAPMessage msg = messageContext.getMessage();
      
      header.setTextContent(seched);
      

      然后使用

      Source src = msg.getSOAPPart().getContent();
      

      要获取内容,将其转换为字符串

      TransformerFactory tf = TransformerFactory.newInstance();
      Transformer transformer = tf.newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      transformer.  setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
      StreamResult result1 = new StreamResult(new StringWriter());
      transformer.transform(src, result1);
      

      替换字符串特殊字符

      String xmlString = result1.getWriter().toString()
      .replaceAll("&lt;", "<").
      replaceAll("&gt;", ">");
      System.out.print(xmlString);
      

      带有固定转义字符的与 dom 相对的字符串

      DocumentBuilder db =  DocumentBuilderFactory.newInstance().newDocumentBuilder();
      InputSource is = new InputSource();
      is.setCharacterStream(new StringReader(xmlString));
      Document doc = db.parse(is);
      Source src123 = new DOMSource(doc);
      

      然后设置回soap消息 msg.getSOAPPart().setContent(src123);

      【讨论】:

        【解决方案4】:

        不要使用createTextNode - 它的重点是在文档中插入一些文本(作为数据),而不是原始 XML 的片段。

        createTextNode 用于文本,createElement 用于元素。

        【讨论】:

        • 感谢您的回复,但我们获得的 xml 数据是动态的,因此我们无法单独构建每个元素并附加到根元素。请建议任何替代方法...谢谢
        【解决方案5】:

        我不希望对标签进行编码。我需要这种方式的输出。

        那么你根本不需要文本节点——这就是createTextNode 不适合你的原因。 (或者更确切地说,它工作正常 - 它只是没有做你想做的事)。您可能应该只解析您的 XML 字符串,然后将结果中的文档节点导入到您的新文档中。

        当然,如果您事先知道元素,首先不要将它们表示为文本 - 使用 createElementcreateAttributecreateTextNodeappendChild 的混合来创建结构。

        JDOM 之类的东西完全有可能使这更简单,但这是基本方法。

        【讨论】:

        • @user1686082:我认为您必须将动态 xml 字符串解析为 DOM 并将 DOM 附加到根目录。这是你想做的吗?
        • @user1686082:我已经为您提供了替代方案:您将 XML 解析为文档,然后将节点导入到新文档中。 (复制并粘贴相同的评论作为对每个答案的回复会给人一种明显的印象,即您还没有真正彻底阅读答案,顺便说一句......)
        • @Roy Ling - 我将 xml 数据作为字符串。如何将此字符串解析为 DOM?对不起,我是新手。请帮助寻找解决方案。
        • @Jon Skeet - 抱歉,我之前没有构建动态 XML 的经验。如果我不能使用 createTextNode(),请寻找替代方案。
        • @user1686082:你可以参考JAXP教程-docs.oracle.com/javase/tutorial/jaxp/intro/dom.html
        【解决方案6】:

        莫汉,

        您不能使用 Document.createTextNode()。该方法会转换(或转义)XML 中的字符。 相反,您需要从 2 个 XML 构建两个单独的文档并使用 importNode

        我像这样使用 Document.importNode() 来解决我的问题:

        构建您的构建器:

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = dbf.newDocumentBuilder();
        Document oldDoc = builder.parse(isOrigXml); //this is XML as InputSource
        Document newDoc = builder.parse(isInsertXml); //this is XML as InputSource
        

        接下来,构建要导入的元素/节点的 NodeList。从 NodeList 创建一个节点。使用 importNode 创建另一个要导入的节点。像这样构建最终 XML 的最后一个节点:

        NodeList nl = newDoc.getElementByTagName("roseindia"); //or whatever the element name is
        Node xmlToInsert = nl.item(0);
        Node importNode = oldDoc.importNode(xmlToImport, true);
        Node target = ((NodeList) oldDoc.getElementsByTagName("ELEMENT_NAME_OF_LOCATION")).item(0);
        target.appendChild(importNode);
        
        Source source = new DOMSource(target);
        ....
        

        剩下的就是标准的 Transformer - StringWriter 到 StreamResult 的东西来获取结果。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-28
          • 2011-08-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多