2

我需要解析一个 xml 文件(我确实使用 JAXB 解析),但我想将 Xml 文件值的某些部分放入一个字符串中。在我上网后,可以通过使用 CDATA 来实现。以下链接讨论了 CDATA。但我确实对代码有疑问。我应该在哪里以及如何指定我希望将哪些元素作为 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>
4

2 回答 2

1

您可以使用为此用例指定的@XmlAnyElementan 。DomHandler

成员处理程序

注释允许您将 XML 文档的@XmlAnyElement某些部分保留为 XML。默认情况下,这被保存为 DOM 节点。通过实现 aDomHandler您可以利用替代表示,例如 a 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);
        }
    }

}

结构

下面是一个如何从映射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;
    }

}

输入.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);
        }
    }

}

输出

<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>
于 2012-09-20T13:26:29.110 回答
-1

您的问题标题中对 CDATA 的引用具有误导性。XML 中的 CDATA 部分是 XML 文件的一部分,如下所示:

<![CDATA[ … ]]>

该部分的内容不会被解析为 XML,而是被视为原始字符文本。因此,它是在该部分中&lt;为每个人编写的替代方法。<

CDATA 不是 XML 信息集的一部分。大多数应用程序不会、不能也不应该关心输入文本是写为 CDATA 部分、“普通”文本还是这两者的混合。只有在实际序列化文件表示的非常低级别,您还需要处理空格、缩进、字符编码等内容,CDATA 才重要。这就是您提到的示例:显然有一种方法可以告诉 JAXB 给定的字符串应该呈现为 CDATA 部分或带有字符引用的“普通”XML。

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

于 2012-09-20T14:33:09.343 回答