【问题标题】:Convert from JSON to XML XSD-valid (with Apache Camel or Java)从 JSON 转换为 XML XSD 有效(使用 Apache Camel 或 Java)
【发布时间】:2018-08-21 18:26:03
【问题描述】:

我有一个骆驼路线,可以将文档从 JSON 转换为 XML;对于 XSD 中定义的模式,XML 必须是有效的。目前,转换完成 camel-xmljson (而且我对列表类型有一些自定义的 java 处理)。

唯一不匹配架构的是元素序列,因为转换将顺序更改为字母顺序,因为每个定义的 JSON 不关心顺序。由于需要转换几种可能发生变化的文档类型,因此转换和后续处理尽可能通用是很重要的(我希望它仅适用于 XSD 文件,而不适用于从 XSD 生成的类)。

所以,我正在寻找一种从 JSON 和 XSD 转换为有效 XML 的方法 或者 一种更改 XML 元素序列以匹配来自 XSD 的定义的方法。 有人能指出点什么吗?

【问题讨论】:

  • 您好,欢迎来到本网站。有关使用 XSLT 将 JSON 转换为 XML 的信息,请参阅此链接。这可能会为您指明正确的方向。stackoverflow.com/questions/13007280/…
  • 谢谢。不幸的是,它没有完整的解决方案,而且我缺乏 XSLT 专业知识来做到这一点。

标签: java xml xsd apache-camel


【解决方案1】:

JSON 不关心对象(键值对)的顺序,但它关心数组,所以也许你应该在顺序重要的地方使用 JSON 数组。 无论如何,您可以使用标准 XSLT 3.0 进行这种 JSON/XML 转换,该标准引入了 JSON 到 XML 和 XML 到 JSON 转换的功能。在 Java 中,SAXON XSLT library supports them(包括免费版本在内的所有版本)自 v9.7 起。

以下是从 JSON 输入 (link to full XSLT) 应用转换的 XSLT 样式表的摘录:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.w3.org/2005/xpath-functions" expand-text="yes"
    xmlns:my-prefix="urn:the:namespace:of:my:xsd">
    <!-- Reference example for JSON to XML transformation: https://www.saxonica.com/papers/xmlprague-2016mhk.pdf -->
    <!-- expand-text option allows to use text value templates in XSLT 3.0 -->
    <xsl:output encoding="UTF-8" indent="yes" method="xml" />

    <xsl:template name="xsl:initial-template">
        <xsl:apply-templates select="json-to-xml(.)" />
    </xsl:template>

<!-- This is just an example of applying a template when matching some key from JSON. --> 
    <xsl:template match="map[@key='key_of_something_to_change']">
        <!-- Fill in whith whatever transformation you want to apply in this case. Plenty of examples to change order of XML elements, such as:
         https://stackoverflow.com/questions/37442799/xslt-change-element-order
          -->
        ...
    </xsl:template>
...

</xsl:stylesheet>

然后是一些示例代码以使用 Java 中的 XSLT,假设 SAXON XSLT >= 9.7 在您的类路径中(此示例将输入 JSON 作为字符串并将结果输出到 System.out 仅用于测试,但您可以适应使用 SAXON API 轻松处理其他类型的输入/输出):

import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.s9api.Xslt30Transformer;
import net.sf.saxon.s9api.XsltExecutable;
import net.sf.saxon.trace.XSLTTraceListener;

...

    private static final XsltExecutable JSON_TO_XML_XSLT_EXEC;
    static
    {
        try
        {
            final Processor xsltProc = new Processor(false);
            JSON_TO_XML_XSLT_EXEC = xsltProc.newXsltCompiler().compile(new StreamSource(new File("/path/to/my/xslt/stylesheet/file"));
        }
        catch (final SaxonApiException e)
        {
            throw new RuntimeException("Cannot create XSLT processor for my stylesheet", e);
        }
   }

   private static void convertJsonToXml(final String inputJson, final Path outXmlFile)
    {
        final Xslt30Transformer xslt = JSON_TO_XML_XSLT_EXEC.load30();
        /*
         * Line below is useful for debugging, esp. to see what the output from the json-to-xml function looks like before further processing. Else remove it.
         */
        xslt.setTraceListener(new XSLTTraceListener());

        try
        {
            xslt.setGlobalContextItem(new XdmAtomicValue(inputJson));
            /*
             * Call default template "xsl:initial-template"
             */
            xslt.callTemplate(null, xslt.newSerializer(System.out));
        }
        catch (final SaxonApiException e)
        {
            throw new RuntimeException("Failed to apply XSLT", e);
        }
   }

【讨论】:

  • 关于在顺序重要的地方使用 JSON 数组:这将需要在太多其他依赖格式的系统上进行更改。链接的 XSLT 不会在生成的 xml 中创建元素,还是我遗漏了什么?
  • 我提到的 github 上的链接 XSLT 是针对特定用例的,是的,它确实在 XACML 命名空间 (XACML schema) 中创建了 XML 元素。每当您在其中看到 &lt;xacml:something&gt; 时,它就是一个输出 XML 元素。实际上,一般来说,任何不在 XSL 命名空间中的元素都应该被输出。
猜你喜欢
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多