-1

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

<?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>
                     <null key="value"/> 
                  </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,依此类推。

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

<?xml version="1.0" encoding="UTF-8"?>
<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>

感谢 Martin Honnen 的 XSLT,实现了输出:

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

当我的源系统以奇怪的方式表示 null 时,就会出现问题。如果字段值为空,则传入数据为:

<?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>
                     <null key="value"/>
                  </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>

脚本正在加扰值,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
   <Rows>
      <Row>
         <F1>1A</F1>
         <F2>1B</F2>
         <F3>1C</F3>
      </Row>
      <Row>
         <F1>2A</F1>
         <F2>2C</F2>
      </Row>
      <Row>
         <F1>3A</F1>
         <F2>3B</F2>
         <F3>3C</F3>
      </Row>
   </Rows>
</Root>

在上面的例子中,F2 的值为空。在输出中 F3 元素消失,F3 字段的值作为 F2 字段的值跳跃。预期输出为:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
   <Rows>
      <Row>
         <F1>1A</F1>
         <F2>1B</F2>
         <F3>1C</F3>
      </Row>
      <Row>
         <F1>2A</F1>
         <F2/>
        <F3>2C</F3>
      </Row>
      <Row>
         <F1>3A</F1>
         <F2>3B</F2>
         <F3>3C</F3>
      </Row>
   </Rows>
</Root>

作为解决方案,我尝试通过将原始语句从

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

<xsl:apply-templates select="fn:map/fn:string[@key = 'value'] | fn:map/fn:null[@key = 'value']"/>    

但是改变它不包括 element <null key="value"/>。我是 XSLT 和 XPath 的新手,需要帮助来解决这个问题。

4

1 回答 1

0
    <?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']/translate(normalize-

space(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'] | fn:map/fn:null[@key = 'value']"/>    
        </Row>
    </xsl:template>

<xsl:template match="fn:string[@key = 'value'] |fn:map/fn:null[@key = 'value']">


        <xsl:element name="{let $pos := position() return $label-names[$pos]}">{.}</xsl:element>
    </xsl:template>

</xsl:stylesheet>
于 2017-11-14T10:24:09.193 回答