当前位置: 首页 > 知识库问答 >
问题:

JAXB-加载具有不同名称空间的XML文件

袁博
2023-03-14

我需要加载XML文件,但存在两种相同的文件格式,只是名称空间不同-在我的简化示例中,apple

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:container xmlns:ns2="apple">
</ns2:container>

pear

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:container xmlns:ns2="pear">
</ns2:container>

XmlRootElement引用了一个特定的名称空间,因此我不能以相同的方式处理这两个文件:

public class NamespaceTest {
    @XmlRootElement(namespace = "apple")
    public static class Container {
    }

    public static void main(final String[] args) throws Exception {
        // Correct namespace - works
        unmarshall("""
                <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                <ns2:container xmlns:ns2="apple">
                </ns2:container>
            """);

        // Incorrect namespace - doesn't work
        unmarshall("""
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <ns2:container xmlns:ns2="pear">
            </ns2:container>
            """);
        }

        private static void unmarshall(final String xml) throws Exception {
            try (Reader reader = new StringReader(xml)) {
                System.out.println(JAXBContext.newInstance(Container.class).createUnmarshaller().unmarshal(reader));
            }
        }
    }
}

给出输出:

com.my.app.NameSpaceTest$Container@77167fb7
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"pear", local:"container"). Expected elements are <{apple}container>

目前,我已经以一种次优的方式进行了工作,通过使用https://stackoverflow.com/a/50800021-但如果可能的话,我想将其转移到JAXB中。

public class NameSpaceTest {
    @XmlRootElement(namespace = "apple")
    public static class Container {
    }

    public static void main(final String[] args) throws Exception {
        // Correct namespace
        unmarshall("""
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <ns2:container xmlns:ns2="apple">
            </ns2:container>
            """);

        // Incorrect namespace
        unmarshall("""
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <ns2:container xmlns:ns2="pear">
            </ns2:container>
            """);
        }

        private static void unmarshall(final String xml) throws Exception {
        try (Reader reader = new TranslatingReader(new BufferedReader(new StringReader(xml))) {
            @Override
            public String translate(final String line) {
            return line.replace("pear", "apple");
            }
        }) {
            System.out.println(JAXBContext.newInstance(Container.class).createUnmarshaller().unmarshal(reader));
        }
    }

    /** @see <a href="https://stackoverflow.com/a/50800021">Source</a> */
    private abstract static class TranslatingReader extends Reader {
        private final BufferedReader input;
        private StringReader output = new StringReader("");

        public TranslatingReader(final BufferedReader input) {
            this.input = input;
        }

        public abstract String translate(final String line);

        @Override
        public int read(final char[] cbuf, int off, int len) throws IOException {
            int read = 0;

            while (len > 0) {
            final int nchars = output.read(cbuf, off, len);

            if (nchars == -1) {
                final String line = input.readLine();

                if (line == null) {
                break;
                } else {
                output = new StringReader(translate(line) + System.lineSeparator());
                }
            } else {
                read += nchars;
                off += nchars;
                len -= nchars;
            }
            }

            if (read == 0) {
            read = -1;
            }

            return read;
        }

        @Override
        public void close() throws IOException {
            input.close();
            output.close();
        }
    }
}

输出:

com.my.app.NameSpaceTest$Container@6ce139a4
com.my.app.NameSpaceTest$Container@18ce0030

共有1个答案

弓温书
2023-03-14

在读取数据时过滤数据是正确的方法(如果您必须处理词汇表的版本和变体,JAXB或一般的数据绑定不是理想的技术选择)。但是使用SAX过滤器过滤它,而不是在流级别。

或者,在使用JAXB处理数据之前,使用XSLT转换规范化数据。

 类似资料:
  • 我从 3 个不同的客户端收到 3 个不同的 xml 输入: 来自客户端1的输入1:(命名空间前缀:,命名空间url:) 来自客户端 2 的输入 2:(命名空间前缀:,命名空间 URL:) 从客户端3输入3:(名称空间前缀: 时,< li >调用< code>String.replace() 这让我想到这种变量命名空间的方法是否应该完全可以接受。如果有什么可以改进此代码的方法,那么我要求社区在答案/

  • 我是XML和JAXB的新手。我读了很多关于XML、名称空间声明等的文章,但我目前面临着一个无法解决的JAXB问题。EPO上有一个关于响应文档的XSD文件。我可以与客户端一起调用EPO web服务并获取返回文档。我将显示这样一个返回文档的第一行。 正如您所看到的,定义了多个名称空间,但在文档正文中使用的名称空间只有两个,即ns2和NS3。我的问题是解组ns3:register-documents实体

  • 问题内容: 我有一个这样的架构层次结构: 一个文件夹中的所有文件都具有相同的命名空间。 现在,我想将名称空间映射到特定的Java包(我不能更改名称空间)。 我找到了将架构绑定到程序包的解决方案。但是然后我必须为每个xsd文件创建一个条目: 有没有一种方法可以直接定义名称空间和程序包名称之间的绑定? 另一种方法是在maven中定义包: 但是然后我必须为每个文件夹创建一个执行,这并不是我真正想要的。

  • 问题内容: 我正在做这个小项目,我的任务是读取xml文件并进行解析,以便可以将其存储在类中。这是xml示例。它是用SOAP编写的,我要做的就是获取 xmlns:ns2="http://abc.examples.com 问题答案: 要使用Java中的命名空间进行XPath查询,我相信您需要执行以下操作: 您还需要先调用;,然后再创建来解析文档。

  • 问题内容: 有“原始” XML 以这种方式解析XML 然后我试图通过XPath提取会话ID 在这里测试 http://www.xpathtester.com/xpath/678ae9388e3ae2fc8406eb8cf14f3119 当XML简化为此 这个XPath可以完成工作 如何使用Java从“原始” XML中提取会话ID? 更新:JDK 1.6 问题答案: 答案是您需要正确使用名称空间和名

  • 问题内容: 我得到了以下XML: 跟随XPath不起作用意味着没有任何打印内容,例如“ data”元素不存在: /root/items/item/details/data 但是,当我删除“数据”元素的“ xmlns”名称空间属性时,将打印其内容。在不删除“数据”元素的“ xmlns”命名空间属性的情况下,xpath表达式应该如何工作? 我正在使用SAXON和XSL 1.0。 问题答案: 这是XPa