JAXB编组XML的部分,并保持原始名称前缀

发布于 2025-01-17 19:35:44 字数 3619 浏览 1 评论 0原文

我正在使用以下插件来生成JAXB类。然后,我从文件系统中阅读了一些XML,然后将其删除为生成的JAXB类。这些课程包含我需要单独拆卸的条目的集合,进行一些业务逻辑,并为每个部分取消分组,并将其存储为XML零件。因此,实际上我正在做XML->对象(进行一些业务逻辑) - >我存储在某个地方的较小的XML。问题是,文件系统中的XML具有正确的名称空间前缀(例如TCA,TCB,TCC),并且在将这些较小的部分编码回XML时,JAXB创建了自己的名称空间前缀,例如NS1,NS2,NS3,NS3。是否可以像原始文件一样具有TCA,TCB,TCC?但是也许不是要定义自己的前缀映射,因为我永远不知道我的文件系统会出现哪些前缀。一些外部聚会将来可能会改变它们,我只想保留原始聚会。 Belo是我的代码。

代码生成插件:

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>${jaxb2-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sources>
                        <source>src/main/resources/my.xsd</source>
                    </sources>
                    <outputDirectory>${basedir}/target/generated-sources/java</outputDirectory>
                    <clearOutputDir>false</clearOutputDir>
                </configuration>
            </plugin>

代码

        JAXBContext jaxbContext = JAXBContext.newInstance(MyRoot.class);

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        while (streamReader.hasNext()) {
            if (streamReader.isStartElement()) {
                if (streamReader.getName() != null && streamReader.getName().getLocalPart() != null) {
                    String localPart = streamReader.getName().getLocalPart();
                    if (localPart.equalsIgnoreCase(XmlElements.CAR)) {
                        JAXBElement<Car> carJAXBElement = unmarshaller.unmarshal(streamReader, Car.class);
                        //doing some business logic 
                        JAXBContext context = JAXBContext.newInstance(Car.class);
                        Marshaller m = context.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                        StringWriter sw = new StringWriter();
                        m.marshal(carJAXBElement, sw);
                        String result = sw.toString();  //the result has namespaces prefixes changed
                        //and then saving one car xml part somewhere
                       
                    }
                }
            }
            streamReader.next();

XML文件

原始文件:

<?xml version="1.0" encoding="UTF-8"?>
<tca:myroot xmlns:tca="http://myspec/tca/1.0" >
    <tca:car>
        <tca:owner>
            <tca:name>
            </tca:name>
        </tca:owner>
    </tca:car>
    <tca:car>
        <tca:owner>
            <tca:name>
            </tca:name>
        </tca:owner>
    </tca:car>
</tca:myroot>

chandered car xml part:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns4:car xmlns:ns4="http://myspec/tca/1.0" >
    <ns4:owner>
        <ns4:name>
        </ns4:name>
    </ns4:owner>
</ns4:car>

编组后,是否可以在那些小型汽车零件中有原始名称空间前缀?

I am using below plugin to generate jaxb classes. I then read some XML from filesystem and unmarshall it to generated jaxb classes. Those classes has collection of entries that I need to unmarshall separately, do some business logic and for each part unmarshalled and store them as xml parts. So in fact I am doing XML -> Object (to do some business logic) -> smaller XMLs which I am storing somewhere. Problem is that the XML in filesystem has correct namespaces prefixes (like tca, tcb, tcc) and while marshalling those smaller parts back to xml, jaxb creates its own namespaces prefixes like ns1, ns2, ns3. Is it possible to have tca, tcb, tcc as in original file ? But maybe not to define my own prefixes map because I never know what prefixes will come to my filesystem. Some external party may change them in future and I only want to keep original ones. Belo is my code.

Code generation plugin:

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>${jaxb2-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sources>
                        <source>src/main/resources/my.xsd</source>
                    </sources>
                    <outputDirectory>${basedir}/target/generated-sources/java</outputDirectory>
                    <clearOutputDir>false</clearOutputDir>
                </configuration>
            </plugin>

The code

        JAXBContext jaxbContext = JAXBContext.newInstance(MyRoot.class);

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        while (streamReader.hasNext()) {
            if (streamReader.isStartElement()) {
                if (streamReader.getName() != null && streamReader.getName().getLocalPart() != null) {
                    String localPart = streamReader.getName().getLocalPart();
                    if (localPart.equalsIgnoreCase(XmlElements.CAR)) {
                        JAXBElement<Car> carJAXBElement = unmarshaller.unmarshal(streamReader, Car.class);
                        //doing some business logic 
                        JAXBContext context = JAXBContext.newInstance(Car.class);
                        Marshaller m = context.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                        StringWriter sw = new StringWriter();
                        m.marshal(carJAXBElement, sw);
                        String result = sw.toString();  //the result has namespaces prefixes changed
                        //and then saving one car xml part somewhere
                       
                    }
                }
            }
            streamReader.next();

The xml files

Original file:

<?xml version="1.0" encoding="UTF-8"?>
<tca:myroot xmlns:tca="http://myspec/tca/1.0" >
    <tca:car>
        <tca:owner>
            <tca:name>
            </tca:name>
        </tca:owner>
    </tca:car>
    <tca:car>
        <tca:owner>
            <tca:name>
            </tca:name>
        </tca:owner>
    </tca:car>
</tca:myroot>

Marshalled car xml part:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns4:car xmlns:ns4="http://myspec/tca/1.0" >
    <ns4:owner>
        <ns4:name>
        </ns4:name>
    </ns4:owner>
</ns4:car>

Is it possible to have original namespaces prefixes in those small car parts after marshalling them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月竹挽风 2025-01-24 19:35:44

因此,尽管没有答案,但我还是自己想知道。因此,我正在为将来的搜索者添加信息 - 如果您发现它有用,请标记我的答案是有效的,因为我不想自己做。

我使用了spaceprefixmapper,其中有映射前缀 - &gt;每个名称空间的名称空间URI从其第一个元素中读取XML文件中的命名空间。它运行良好,但是Sonar抱怨我正在使用Sun Internallass:

 JAXBContext context = JAXBContext.newInstance(clazz);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper(namespaces));

因此我使用了package-info.java方法。我注意到,jaxb2-maven-plugin xjc目标创建默认的软件包info.java。在此文件中,可以将自己的名称空间前缀添加到名称空间URI映射中。然后,我使用Maven-Resources-Plugin将我自己的Package-info.java复制到生成类的包装。最后,当邮政使用者将对象转换回XML文件时,它使用我的Package-info.java和原始名称空间前缀而不是NS1,NS2,等。

<plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <overwrite>true</overwrite>
                            <outputDirectory>${basedir}/target/generated-sources/java/package_where_default_package_info_is_generated</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${basedir}/src/main/resources/bindings</directory>
                                    <include>package-info.java</include>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>        

So despite there were no answers, I've figured it out by myself.. So I am adding info for future searchers - please mark my answer as valid if u will find it useful because I don't want to do it by myself.

I used NamespacePrefixMapper where I had mapping prefix -> namespace uri for each namespace read in xml file from its first element. It worked fine, but Sonar was complaining that I am using sun internal classes:

 JAXBContext context = JAXBContext.newInstance(clazz);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper(namespaces));

So I then used package-info.java approach. I noticed, that jaxb2-maven-plugin xjc goal creates default package-info.java. Inside this file it is possible to add your own namespace prefix to namespace uri mapping. Then I used maven-resources-plugin to copy my own package-info.java to package of generated classes. Finally when marshaller is converting objects back to xml files, it uses my package-info.java and original namespace prefixes are preserved instead of ns1, ns2, etc.

<plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <overwrite>true</overwrite>
                            <outputDirectory>${basedir}/target/generated-sources/java/package_where_default_package_info_is_generated</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${basedir}/src/main/resources/bindings</directory>
                                    <include>package-info.java</include>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>        
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文