2012-09-20 44 views
2

我需要解析一个xml文件(我使用JAXB解析),但是我想将Xml文件值的一部分转换为字符串。在网上冲浪之后,可以使用CDATA。以下链接讨论CDATA。但是我对代码有疑问。我在哪里以及如何指定我想要将哪些元素作为CDATA进行处理。在JAXB中处理CDATA

http://jaxb.java.net/faq/JaxbCDATASample.java

我的XML如下所示。

<root> 
    <Service>CDATASERVICE</Service> 
    <Child> 
     <param> 
      <value> 
       <struct> 
        <member> 
         <name>Servicename</name> 
         <value>service1</value> 
        </member> 
       </struct> 
      </value> 
     </param> 
     <param> 
      <value> 
       <struct> 
        <member> 
         <name>item1</name> 
         <value>36</value> 
        </member> 
        <member> 
         <name>Cdata</name> 
         <value> 
          <struct> 
           <member> 
            <name>services</name> 
            <value> 
             <array> 
              <data> 
               <value>ABCD</value> 
              </data> 
             </array> 
            </value> 
           </member> 
          </struct> 
         </value> 
        </member> 
        <member> 
         <name>item2</name> 
         <value> 
          <int>10</int> 
         </value> 
        </member> 
       </struct> 
      </value> 
     </param> 
    </Child> 
</root> 

我想从上面的XML文件中将以下部分作为字符串,我怎么能得到这一点。

    <name>Cdata</name> 
          <value> 
           <struct> 
            <member> 
             <name>services</name> 
             <value> 
              <array> 
               <data> 
                <value>ABCD</value> 
               </data> 
              </array> 
             </value> 
            </member> 
           </struct> 
          </value> 
+0

这是你如何包装CDATA:http://www.w3schools.com/xml/xml_cdata.asp – popfalushi

回答

1

您可以使用这个用例中指定的DomHandler@XmlAnyElement

MemberHandler

@XmlAnyElement注释可以让你保持一个XML文档作为XML的部分。默认情况下,这保存为DOM节点。通过实施DomHandler,您可以利用替代表示法,例如String

package forum12512299; 

import java.io.*; 
import javax.xml.bind.ValidationEventHandler; 
import javax.xml.bind.annotation.DomHandler; 
import javax.xml.transform.Source; 
import javax.xml.transform.stream.*; 

public class MemberHandler implements DomHandler<String, StreamResult> { 

    private static final String MEMBER_START_TAG = "<member>"; 
    private static final String MEMBER_END_TAG = "</member>"; 

    private StringWriter xmlWriter; 

    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) { 
     xmlWriter = new StringWriter(); 
     return new StreamResult(xmlWriter); 
    } 

    public String getElement(StreamResult rt) { 
     String xml = rt.getWriter().toString(); 
     int beginIndex = xml.indexOf(MEMBER_START_TAG) + MEMBER_START_TAG.length(); 
     int endIndex = xml.indexOf(MEMBER_END_TAG); 
     return xml.substring(beginIndex, endIndex); 
    } 

    public Source marshal(String n, ValidationEventHandler errorHandler) { 
     try { 
      String xml = MEMBER_START_TAG + n.trim() + MEMBER_END_TAG; 
      StringReader xmlReader = new StringReader(xml); 
      return new StreamSource(xmlReader); 
     } catch(Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 

STRUCT

下面是的DomHandler是如何从一个@XmlAnyElement映射引用的例子。

package forum12512299; 

import java.util.List; 
import javax.xml.bind.annotation.*; 

@XmlRootElement 
public class Struct { 

    private List<String> members; 

    @XmlAnyElement(MemberHandler.class) 
    public List<String> getMembers() { 
     return members; 
    } 

    public void setMembers(List<String> members) { 
     this.members = members; 
    } 

} 

的input.xml

下面我简单的XML文档到一个有趣的现象:

<struct> 
    <member> 
     <name>item1</name> 
     <value>36</value> 
    </member> 
    <member> 
     <name>Cdata</name> 
     <value> 
      <struct> 
       <member> 
        <name>services</name> 
        <value> 
         <array> 
          <data> 
           <value>ABCD</value> 
          </data> 
         </array> 
        </value> 
       </member> 
      </struct> 
     </value> 
    </member> 
    <member> 
     <name>item2</name> 
     <value> 
      <int>10</int> 
     </value> 
    </member> 
</struct> 

演示

package forum12512299; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Struct.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum12512299/input.xml"); 
     Struct struct = (Struct) unmarshaller.unmarshal(xml); 

     for(String string : struct.getMembers()) { 
      System.out.println(string); 
     } 
    } 

} 

欧tput的

<name>item1</name><value>36</value> 

<name>Cdata</name><value><struct><member><name>services</name><value><array><data><value>ABCD</value> 
          </data> 
         </array> 
        </value> 

<name>item2</name><value><int>10</int> 
     </value> 
0

在你的问题的标题CDATA参考是一种误导。 XML中的CDATA部分是这样写的XML文件的一部分:

<![CDATA[ … ]]> 

该部分的内容不被解析为XML,而是作为原始字符的文本处理。因此,该部分中的每<是另一种编写&lt;的替代方法。

CDATA不是XML信息集的一部分。大多数应用程序不会,也不应该关心输入文本是写成CDATA部分,还是“正常”文本或混合这两种文本。只有在实际的序列化文件表示的非常低的层次上,你也可以处理诸如空白,缩进,字符编码等等,CDATA是否重要。这就是你提到的例子:显然有一种方法可以告诉JAXB一个给定的字符串应该被呈现为一个CDATA节或者作为具有字符引用的“普通”XML。

对于您的应用程序,这似乎没什么用处。为了使用CDATA,您的输入XML将已经必须包含CDATA标记。因为它没有(根据我们的例子),解析器别无选择,只能将其视为格式良好的XML。 answer by Blaise已经指出,您可能仍然能够在数据结构中“按原样”表示该子树,无论是作为DOM节点还是作为XML字符串。