微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何遍历 xslt3.0 中的当前组并打印每个值

如何解决如何遍历 xslt3.0 中的当前组并打印每个值

我有一个格式为 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"
},"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 对应的值数组中添加其各自的 EffectiveDate 和 lastname。 下面是我试过的 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",{
    "PersonId": "80","LASTNAME": ""
        }
    ]
}

]

解决方法

你很接近。这是构建变量的方法:

<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>
,

请注意,作为替代方法,您还可以将 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(),'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 版本中看到类似的选择。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。