java - 从 JSON 转换为 XML XSD 有效(使用 Apache Camel 或 Java)
问题描述
我有一条骆驼路线,可以将文档从 JSON 转换为 XML;对于 XSD 中定义的模式,XML 必须是有效的。目前,转换是使用 camel-xmljson完成的 (我有一些针对列表类型的自定义 java 处理)。
唯一不匹配架构的是元素序列,因为转换将顺序更改为字母顺序,因为每个定义的 JSON 不关心顺序。由于需要转换几种可能发生变化的文档类型,因此转换和后续处理尽可能通用是很重要的(我希望它仅适用于 XSD 文件,而不适用于从 XSD 生成的类)。
因此,我正在寻找一种从 JSON 和 XSD 转换为有效 XML 的方法,或者一种改变 XML 元素序列以匹配 XSD 定义的方法。有人能指出点什么吗?
解决方案
JSON 不关心对象(键值对)中的顺序,但它关心数组中的顺序,所以也许您应该在顺序重要的地方使用 JSON 数组。无论如何,您可以使用标准 XSLT 3.0 进行这种 JSON/XML 转换,该标准引入了 JSON 到 XML 和 XML 到 JSON 转换的功能。在 Java 中,自 v9.7 起,SAXON XSLT 库就支持它们(包括免费版本在内的所有版本)。
以下是从 JSON 输入应用转换的 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);
}
}
推荐阅读
- bash - 在 linux 文件中逐行比较
- javascript - 无法选择动态生成的 HTML 元素(使用 Handlebars Block 助手生成)
- python - 根据两列中的值匹配熊猫数据框中的行
- python - 使用 Google Vision API 从图像中提取分块文本
- php - 如何从数据库所有表中删除所有记录
- c++ - 代码块 16 位消息
- javascript - 我在函数之外提到的变量“x”我猜有一些问题。函数没有访问变量不知道为什么
- typescript - ASP.NET Core MVC + Vue + 单文件组件
- php - 在 codignator 中的日期之间获取数据
- android - 如何在 VHAL android Automotive 中处理自定义车辆属性?