【问题标题】:how to loop through current-group in xslt3.0 and print each value如何在 xslt3.0 中循环当前组并打印每个值
【发布时间】:2021-08-13 10:24:33
【问题描述】:

我有一个格式的输入 json

[
{
    "PERSON_ID": 78,
    "EFFECTIVE_START_DATE": "2013-12-02 00:00:00",
    "LAST_NAME": "Hulk78"
},
{
    "PERSON_ID": 78,
    "EFFECTIVE_START_DATE": "2020-06-24 07:29:26",
    "LAST_NAME": "Hulks78"
},
{
    "PERSON_ID": 79,
    "EFFECTIVE_START_DATE": "2015-12-02 00:00:00",
    "LAST_NAME": "Hulk79"
},
{
    "PERSON_ID": 79,
    "EFFECTIVE_START_DATE": "2020-07-24 07:29:26",
    "LAST_NAME": "Hulks79"
},
{
    "PERSON_ID": 80,
    "EFFECTIVE_START_DATE": "2013-12-10 00:00:00",
    "LAST_NAME": "Hulk15"
}

]

预期输出

[
{
    "PersonId": 78,
    "value": [
        {
            "EffectiveDate": "2013-12-02 00:00:00",
            "lastName":"Hulk78"
        },
        {
            "EffectiveDate": "2020-06-24 07:29:26",
            "lastName":"Hulks78"
        }
    ]
}
....

]

我想通过对 person_id 值进行分组来转换输入 json,并为每个组将其各自的有效日期和姓氏添加到与该人员 ID 对应的值数组中。 下面是我试过的xslt。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0"
xmlns="http://www.w3.org/2005/xpath-functions" xpath-default-namespace="http://www.w3.org/2005/xpath-functions" expand-text="yes">
<xsl:param name="input"/>
<xsl:output method="text"/>

<xsl:template name="xsl:initial-template">
    <xsl:variable name="input-as-xml" select="json-to-xml($input)"/>
    <xsl:variable name="transformed-xml" as="element(array)">
        
      <array>
          <xsl:for-each-group select="$input-as-xml" group-by="//number[@key='PERSON_ID']">
              <map>
                  <string key="PersonId">
                      <xsl:value-of select="current-grouping-key()"/>
                  </string>
                 
                  <array key="Value">
                      <xsl:for-each select="current-group()">
                      <map>
                          <string key="EffectiveDate">
                              <xsl:value-of select="../string[@key='EFFECTIVE_START_DATE']"/>
                          </string>
                          <string key="LASTNAME">
                              <xsl:value-of select="@LAST_NAME"/>
                          </string>
                      </map>
                          
                  </xsl:for-each> 
                  </array>
              </map>
              
          </xsl:for-each-group>
      </array>       
    </xsl:variable>
    <xsl:value-of select="xml-to-json($transformed-xml)"/>
</xsl:template>

样式表>

谁能帮助我了解如何从当前组中取出每个生效日期和姓氏。

这是我得到的输出

[
{
    "PersonId": "78",
    "Value": [
        {
            "EffectiveDate": "",
            "LASTNAME": ""
        }
    ]
},
{
    "PersonId": "79",
    "Value": [
        {
            "EffectiveDate": "",
            "LASTNAME": ""
        }
    ]
},
{
    "PersonId": "80",
    "Value": [
        {
            "EffectiveDate": "",
            "LASTNAME": ""
        }
    ]
}

]

【问题讨论】:

  • 您能否向我们展示您生成的 JSON 格式的输出文件?
  • [{"PersonId":"78","Value":[{"EffectiveDate":"","LASTNAME":""}]},{"PersonId":"79", "值":[{"EffectiveDate":"","LASTNAME":""}]},{"PersonId":"80","Value":[{"EffectiveDate":"","LASTNAME":" "}]}]
  • 这是我得到的输出...我无法添加有效数据和姓氏值。
  • 请在问题中添加输出json(在预期输出之前,所以我们看到它是结构化的

标签: xslt xslt-2.0 xslt-grouping xslt-3.0


【解决方案1】:

请注意,作为一种替代方法,您还可以将 JSON 直接转换为 XDM 3.1 映射和数组,并对这些数据进行分组,而无需来回转换为 XML;唯一的缺点是 XSLT 3 缺少创建数组的指令,因此您必须依赖 XPath 3.1 表达式,例如 [ ]array { },这有时需要您在模板中使用函数调用。

您的示例是

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
  <xsl:function name="mf:group" as="map(*)*">
    <xsl:param name="persons" as="map(*)*"/>
    <xsl:for-each-group select="$persons" group-by="?PERSON_ID">
      <xsl:sequence select="map { 'PersonId' : current-grouping-key(), 
                                  'value' : array { 
                                               current-group() ! map { 'EffectiveDate ' : ?EFFECTIVE_START_DATE, 
                                                                        'lastName' : ?LAST_NAME } } }"/>
    </xsl:for-each-group>
  </xsl:function>

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

  <xsl:param name="json-input" as="xs:string"/>

  <xsl:template name="xsl:initial-template">
    <xsl:apply-templates select="parse-json($json-input)"/>
  </xsl:template>

  <xsl:template match=".">
    <xsl:sequence select="array { mf:group(?*) }"/>
  </xsl:template>

</xsl:stylesheet>

JSON -> XML -> JSON 转换的另一个缺点是 XDM 映射中键值对的顺序缺失,这样序列化的 JSON 通常没有您期望的键顺序。 Saxon 的商业版本有一些扩展属性来定义序列化的顺序。

使用 Saxon JS 2.2 及更高版本的 xslt3,您甚至可以使用 -json:data.json 选项直接将 JSON 作为输入提供给转换并使用例如

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
  <xsl:function name="mf:group" as="map(*)*">
    <xsl:param name="persons" as="map(*)*"/>
    <xsl:for-each-group select="$persons" group-by="?PERSON_ID">
      <xsl:sequence select="map { 'PersonId' : current-grouping-key(), 
                                  'value' : array { 
                                               current-group() ! map { 'EffectiveDate ' : ?EFFECTIVE_START_DATE, 
                                                                        'lastName' : ?LAST_NAME } } }"/>
    </xsl:for-each-group>
  </xsl:function>

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

  <xsl:template match=".">
    <xsl:sequence select="array { mf:group(?*) }"/>
  </xsl:template>

</xsl:stylesheet>

我认为我们会在下一个 Saxon Java 市长版本中看到类似的选项。

【讨论】:

    【解决方案2】:

    你很亲密。这是构建变量的方法:

    <xsl:variable name="transformed-xml" as="element()">
      <array>
        <xsl:for-each-group select="$input-as-xml/array/map" group-by="number[@key='PERSON_ID']">
          <map>
            <string key="PersonId">
              <xsl:value-of select="current-grouping-key()"/>
            </string>
            <array key="Value">
              <xsl:for-each select="current-group()">
                <map>
                  <string key="EffectiveDate">
                    <xsl:value-of select="string[@key='EFFECTIVE_START_DATE']"/>
                  </string>
                  <string key="LASTNAME">
                    <xsl:value-of select="string[@key='LAST_NAME']"/>
                  </string>
                </map>
              </xsl:for-each> 
            </array>
          </map>          
        </xsl:for-each-group>
      </array>       
    </xsl:variable>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多