【问题标题】:how to convert json to xml with saxonjs?如何使用 saxonjs 将 json 转换为 xml?
【发布时间】:2022-01-21 18:11:15
【问题描述】:

我需要使用 saxonjs 将 json 转换为 xml,我不知道如何将键与 xml 节点匹配,我正在寻找一些示例,但它们都不适合我,这是我的代码

const issue = {
   id: 1,
   details: {
       type: 'urgent',
       description: 'Description of issue comes here',
       date: '2021-12-12',       
   }
};

saxonJS.transform({
        stylesheetLocation: './issue.sef.json',
        sourceType: 'json',
        sourceText: issue,
        destination: 'serialized',
    }, 'async').then(data => {
        fs.open('output.xml', 'w', function(err, fd) {
            fs.write(fd, data.principalResult, (err2, bytes) => {
                if(err2) {
                    console.log(err2);
                }
            });

        }); 

        res.status(200).send('Ok');
    })
    .catch(err => {
        console.log(err);
        res.status(500).send('error');
    });

这就是我想要实现的输出

<xml>
     <issue id="1">
        <description>
            <![CDATA[
                Description of issue comes here
            ]]>
        </description>
        <type>urgent</type>
        <date>2021-12-12</date>
     </issue>
</xml>

你能帮我处理一下 xslt 模板吗?

【问题讨论】:

    标签: node.js xml xslt-3.0 saxon-js


    【解决方案1】:

    您显示的输入是一个 JavaScript 对象,在 JSON 规范的严格语法规则中它不是 JSON。

    所以我认为最好使用 JSON.stringify 创建 JSON 并将其传递给 XPath 3.1 函数 parse-json 以创建 JSON 或使用 Saxon-JS 2.3 功能获取 JSON 文本,只需确保您正确地JSON.stringifyed 那个对象。

    对于一个看起来很简单的示例 XSLT,为了 XSLT 的可读性,下面的示例只是使用带有 XSLT 源代码的 JavaScript 字符串并通过 Saxon API 运行它:

    const SaxonJS = require("saxon-js");
    
    const issue = {
       id: 1,
       details: {
           type: 'urgent',
           description: 'Description of issue comes here',
           date: '2021-12-12',       
       }
    };
    
    const xslt = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">
      <xsl:output indent="yes" cdata-section-elements="description"/>
      
      <xsl:template match=".">
       <xml>
        <issue id="{?id}">
          <description>{?details?description}</description>
          <type>{?details?type}</type>
          <date>{?details?date}</date>
        </issue>
       </xml>
      </xsl:template>
    </xsl:stylesheet>`;
          
    
    const result = SaxonJS.XPath.evaluate(`transform(map {
      'stylesheet-text' : $xslt,
      'initial-match-selection' : parse-json($json),
      'delivery-format' : 'serialized'
    })?output`,
    [],
    { params : 
        {
            json : JSON.stringify(issue),
            xslt : xslt
        }
    });
    

    当然,最后你可以先把 XSLT 编译成 SEF/JSON,然后按照你的尝试运行。

    为了给您提供一个使用两个不同模板和应用模板的示例 XSLT,以下内容不是使用内联代码处理嵌套对象/映射,而是将其处理到不同的模板:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes" xmlns:map="http://www.w3.org/2005/xpath-functions/map" exclude-result-prefixes="#all">
      <xsl:output indent="yes" cdata-section-elements="description"/>
      
      <xsl:template match=".[. instance of map(*) and map:contains(., 'id')]">
       <xml>
        <issue id="{?id}">
          <xsl:apply-templates select="?details"/>
        </issue>
       </xml>
      </xsl:template>
      
      <xsl:template match=".[. instance of map(*) and map:contains(., 'description')]">      
        <description>{?description}</description>
        <type>{?type}</type>
        <date>{?date}</date>
      </xsl:template>
      
    </xsl:stylesheet>
    

    【讨论】:

    • 谢谢,您的解决方案给了我一些线索,如果我想添加另一个 xsl:template 标签来匹配描述键,我该怎么办?
    • @mapr,键不是数据模型中的项目,JSON 对象映射到 XDM/XPath 3.1 映射,因此您可以匹配例如match=".[. instance of map(*) and map:contains(., 'description')]" 匹配具有名为 description 的键的映射,但您不能将键本身匹配为映射的一部分,除非您处理外部映射的例如 map:keys() 然后设置与字符串匹配的模板description(但您不再有关系或访问地图)。另一种方法是使用json-to-xml,然后为规范定义的 JSON 或函数返回的 XML 格式编写模板
    • @mapr,另请参阅我所做的编辑,我添加了第二个样式表,其中包含更精确的模式以匹配来自输入的两个不同地图,并与包含的 @987654329 的第一个模板推送处理@map/object 到另一个模板。
    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 2012-10-12
    • 2021-07-22
    • 2019-03-27
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    相关资源
    最近更新 更多