使用 XSLT 动态生成 xml [英] dynamic xml generation using XSLT

查看:32
本文介绍了使用 XSLT 动态生成 xml的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有来自 Source 的传入 JSON 数据,其数据和列位于同一有效负载中.在 XSLT 中使用 json-to-xml 我能够生成如下的 XML:

We have incoming JSON data from Source which has data and column in same payload. Using json-to-xml in XSLT I was able to generate XML like following:

<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
   <boolean key="allData">true</boolean>
   <map key="factMap">
      <map key="T!T">
         <array key="rows">
            <map>
               <array key="dataCells">
                  <map>
                     <string key="label">1A</string>
                     <string key="value">1A</string>
                  </map>
                  <map>
                     <string key="label">1B</string>
                     <string key="value">1B</string>
                  </map>
                  <map>
                     <string key="label">1C</string>
                     <string key="value">1C</string>
                  </map>
               </array>
            </map>
            <map>
               <array key="dataCells">
                  <map>
                     <string key="label">2A</string>
                     <string key="value">2A</string>
                  </map>
                  <map>
                     <string key="label">2B</string>
                     <string key="value">2B</string>
                  </map>
                  <map>
                     <string key="label">2C</string>
                     <string key="value">2C</string>
                  </map>
               </array>
            </map>
            <map>
               <array key="dataCells">
                  <map>
                     <string key="label">3A</string>
                     <string key="value">3A</string>
                  </map>
                  <map>
                     <string key="label">3B</string>
                     <string key="value">3B</string>
                  </map>
                  <map>
                     <string key="label">3C</string>
                     <string key="value">3C</string>
                  </map>
               </array>
            </map>
         </array>
      </map>
   </map>
   <map key="detailColumnInfo">
      <map key="Product_vod__c.F1">
         <string key="dataType">string</string>
         <string key="label">F1</string>
      </map>
      <map key="Product_vod__c.F2">
         <string key="dataType">string</string>
         <string key="label">F2</string>
      </map>
      <map key="Product_vod__c.F3">
         <string key="dataType">string</string>
         <string key="label">F3</string>
      </map>
   </map>
</map>

这里每一行都可以在 dataCells 标签下作为标签和值使用.dataCells 下的值代表字段的值,但标签不代表字段名称.字段名称和字段顺序是 detailColumnInfo 标记的一部分.字段/数据的顺序和数量不固定,但目标 XML 应保持固定.例如.传入的数据可以有 10 个字段,数据可以按任何顺序排列,但目标 XML 只能有 2 个字段.为了实现这一点,我相信,在运行时我们必须弄清楚 F1 字段的顺序,并且必须从 dataCells 中选择相应的数据.例如.如果 F1 是字段是 detailColumnInfo 中的第一个字段,那么我必须从所有数据单元(1A、2A、3A)中选取第一个值并生成具有 F1 字段值的目标 XML,依此类推.

Here each row is available under dataCells tag as label and value. Value under dataCells represents value of field however label does not represent field name. Field names and field order is part of detailColumnInfo tag. Order and number of fields/data in is not fixed however target XML shall remain fixed. E.g. incoming data can have 10 fields and data in any order however target XML shall have only 2 fields. To implement this, I believe, on run time we have to figure out the order of F1 field and have to pick corresponding data from dataCells. E.g. if F1 is field is first field in detailColumnInfo then I have to pick first value from all dataCells (1A, 2A, 3A)and generate target XML with value of F1 field and so on.

Detailcolumninfo 标签表示列的详细信息.Detailcolumninfo 中值字段的位置将决定数据单元中字段的位置.对于查询中发布的输入代码片段,如果 F1 是 Detailcolumninfo 中的第一个标签,则 Datacells (1A,2A,3A) 中的第一个值表示 F1 的值.类似地,1B,2B,3B 代表 F2 的值.目标 XML 应如下所示:

Detailcolumninfo tag represents the column details. Position of value field in Detailcolumninfo will determine the position of fields in Datacells. For input code snippet posted in query, if F1 is the 1st label in Detailcolumninfo then first value in Datacells (1A,2A,3A) represents the value of F1. Similarly 1B,2B,3B represents value of F2. Target XML should look like following:

<Root>   
<Rows> 
<Row> 
<F1> 1A </F1> 
<F2> 1B </F2> 
<F3> 1C </F3> 
</Row> 
<Row> 
<F1>2A </F1> 
<F2> 2B </F2> 
<F3> 2C </F3> 
</Row> 
<Row> 
<F1>3A </F1> 
<F2> 3B </F2> 
<F3> 3C </F3> 
</Row> 
</Rows> 

谁能建议可能的解决方案来实现这种动态映射.

Can anyone suggest possible solutions to implement such dynamic mapping.

推荐答案

这里是一个例子,假设您只是想用 key="dataCells"array 元素> 到一个 Row 元素,然后输出它的后代 string,其中 key="value" 包裹在来自 detailColumnInfo 的标签中:

Here is an example that assumes you simply want to map each array element with key="dataCells" to a Row element and then output its descendants string with key="value" wrapped in the label from the detailColumnInfo:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math fn"
    expand-text="yes"
    version="3.0">

    <xsl:param name="json-xml">
        <map xmlns="http://www.w3.org/2005/xpath-functions">
            <boolean key="allData">true</boolean>
            <map key="factMap">
                <map key="T!T">
                    <array key="rows">
                        <map>
                            <array key="dataCells">
                                <map>
                                    <string key="label">1A</string>
                                    <string key="value">1A</string>
                                </map>
                                <map>
                                    <string key="label">1B</string>
                                    <string key="value">1B</string>
                                </map>
                                <map>
                                    <string key="label">1C</string>
                                    <string key="value">1C</string>
                                </map>
                            </array>
                        </map>
                        <map>
                            <array key="dataCells">
                                <map>
                                    <string key="label">2A</string>
                                    <string key="value">2A</string>
                                </map>
                                <map>
                                    <string key="label">2B</string>
                                    <string key="value">2B</string>
                                </map>
                                <map>
                                    <string key="label">2C</string>
                                    <string key="value">2C</string>
                                </map>
                            </array>
                        </map>
                        <map>
                            <array key="dataCells">
                                <map>
                                    <string key="label">3A</string>
                                    <string key="value">3A</string>
                                </map>
                                <map>
                                    <string key="label">3B</string>
                                    <string key="value">3B</string>
                                </map>
                                <map>
                                    <string key="label">3C</string>
                                    <string key="value">3C</string>
                                </map>
                            </array>
                        </map>
                    </array>
                </map>
            </map>
            <map key="detailColumnInfo">
                <map key="Product_vod__c.F1">
                    <string key="dataType">string</string>
                    <string key="label">F1</string>
                </map>
                <map key="Product_vod__c.F2">
                    <string key="dataType">string</string>
                    <string key="label">F2</string>
                </map>
                <map key="Product_vod__c.F3">
                    <string key="dataType">string</string>
                    <string key="label">F3</string>
                </map>
            </map>
        </map>
    </xsl:param>

    <xsl:variable name="label-names" as="xs:string*" select="$json-xml//fn:map[@key = 'detailColumnInfo']/fn:map/fn:string[@key = 'label']/string()"/>

    <xsl:output indent="yes"/>

    <xsl:template match="/" name="xsl:initial-template">
        <xsl:apply-templates select="$json-xml//fn:map[@key = 'factMap']"/>
    </xsl:template>

    <xsl:template match="fn:map[@key = 'factMap']">
        <Root>
            <Rows>
                <xsl:apply-templates select="$json-xml//fn:array[@key = 'rows']/fn:map/fn:array"/>
            </Rows>
        </Root>
    </xsl:template>

    <xsl:template match="fn:array[@key = 'rows']/fn:map/fn:array">
        <Row>
            <xsl:apply-templates select="fn:map/fn:string[@key = 'value']"/>    
        </Row>
    </xsl:template>

    <xsl:template match="fn:string[@key = 'value']">
        <xsl:element name="{let $pos := position() return $label-names[$pos]}">{.}</xsl:element>
    </xsl:template>

</xsl:stylesheet>

输出是

<Root>
   <Rows>
      <Row>
         <F1>1A</F1>
         <F2>1B</F2>
         <F3>1C</F3>
      </Row>
      <Row>
         <F1>2A</F1>
         <F2>2B</F2>
         <F3>2C</F3>
      </Row>
      <Row>
         <F1>3A</F1>
         <F2>3B</F2>
         <F3>3C</F3>
      </Row>
   </Rows>
</Root>

这篇关于使用 XSLT 动态生成 xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆