首页 > 解决方案 > 在展平 JSON 数据后添加几个属性和命名空间前缀

问题描述

在扁平化解析的 JSON 数据之后,我想添加几个属性和命名空间前缀,基于之前的 JSON 数组键分组。这个问题类似于: Add attributes to match parsed json-to-xml map before flatten data

...不同之处在于,在这种情况下,尝试在展平之后添加属性并且没有隧道。尝试实现此目的的原因是控制基于先前 JSON 文件数组分组的添加属性。

我不能使用直接使用“parse-json”处理 JSON 的方法,因为这只是一个最小的 JSON 代码示例。真实数据更大并且来自用户,这意味着一些数据是未知的(因此不能硬编码)。

我的代码在这里可见: https ://xsltfiddle.liberty-development.net/gVAkJ3X/1

您可以在下面找到代码提取:

数据.json

<data>

{
  "ix_hidden": [
    {
    "CompanyName": "Link Inc",
    "OrganisationNumber": "123"
    }
  ],

  "other": [
    {
      "SomethingElse": "Juice"
    }
  ]

}

</data>

XSL:

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xbrli="http://www.example.com/1"
  xmlns:ix="http://www.example.com/2"
  xmlns:tx="http://www.example.com/3"
  >

  <xsl:output method="xml"/>

<!-- Parse JSON to XML -->

  <xsl:template match="data">
  <xbrli:xbrl>
    <xsl:apply-templates select="json-to-xml(.)/*"/>
  </xbrli:xbrl>
</xsl:template>

<!-- Flatten data, exlude high-level key names-->

<xsl:template match="*[@key and not(*)]">
  <xsl:element name="{@key}">
    <xsl:value-of select="."/>
  </xsl:element>

<!-- Add attributes and NS prefix to [ix_hidden] -->

  <xsl:for-each select="*[@key = 'ix_hidden']/*">
    <xsl:attribute name="attributeOne">1</xsl:attribute>
    <xsl:attribute name="attributeTwo">2</xsl:attribute>
    <xsl:attribute name="attributeThree">3</xsl:attribute>
    <xsl:attribute name="attributeFour">4</xsl:attribute>
    <xsl:attribute name="attributeFive">5</xsl:attribute>
  </xsl:for-each>

  <!-- Add attributes and NS prefix to [other] -->

    <xsl:for-each select="*[@key = 'other']/*">
      <xsl:attribute name="contextRef">balance0</xsl:attribute>
    </xsl:for-each>

</xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:ix="http://www.example.com/2" xmlns:xbrli="http://www.example.com/1">
  <CompanyName>Link Inc</CompanyName>
  <OrganisationNumber>123</OrganisationNumber>
  <SomethingElse>Juice</SomethingElse>
</xbrli:xbrl>

想要的结果

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:ix="http://www.example.com/2" xmlns:xbrli="http://www.example.com/1">
  <ix:CompanyName attributeOne="1" attributeTwo="2" attributeThree="3" attributeFour="4" attributeFive="5">Link Inc</ix:CompanyName>
  <ix:OrganisationNumber attributeOne="1" attributeTwo="2" attributeThree="3" attributeFour="4" attributeFive="5">123</ix:OrganisationNumber>
  <tx:SomethingElse contextRef="balance0">Juice</tx:SomethingElse>
</xbrli:xbrl>

标签: xmlxsltxslt-2.0xslt-3.0

解决方案


我认为以下(https://xsltfiddle.liberty-development.net/gVAkJ3X/2)可能会有所帮助:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xbrli="http://www.example.com/1"
  xmlns:ix="http://www.example.com/2"
  xmlns:tx="http://www.example.com/3"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="fn"
  expand-text="yes"
  >
    
  <xsl:attribute-set name="s1">
    <xsl:attribute name="attributeOne">1</xsl:attribute>
    <xsl:attribute name="attributeTwo">2</xsl:attribute>
    <xsl:attribute name="attributeThree">3</xsl:attribute>
    <xsl:attribute name="attributeFour">4</xsl:attribute>
    <xsl:attribute name="attributeFive">5</xsl:attribute>      
  </xsl:attribute-set>
  
  <xsl:attribute-set name="s2">
    <xsl:attribute name="contextRef">balance0</xsl:attribute>
  </xsl:attribute-set>

  <xsl:output method="xml" indent="yes"/>

<!-- Parse JSON to XML -->

  <xsl:template match="data">
      <xbrli:xbrl>
        <xsl:apply-templates select="json-to-xml(.)/*"/>
      </xbrli:xbrl>
  </xsl:template>

<!-- Flatten data, exlude high-level key names-->

<xsl:template match="*[@key and not(*)]">
  <xsl:element name="{@key}">{.}</xsl:element>
</xsl:template>

<!-- Add attributes and NS prefix to [ix_hidden] -->

<xsl:template match="fn:array[@key = 'ix_hidden']//*[@key and not(*)]">
    <xsl:element name="ix:{@key}" namespace="http://www.example.com/2" use-attribute-sets="s1">{.}</xsl:element>
</xsl:template>

<!-- Add attributes to [other] -->

<xsl:template match="fn:array[@key = 'other']//*[@key and not(*)]">
    <xsl:element name="tx:{@key}" namespace="http://www.example.com/3" use-attribute-sets="s2">{.}</xsl:element>
</xsl:template>

</xsl:stylesheet>

推荐阅读