我们从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下的值表示字段的值,但label不表示字段名称。字段名称和字段顺序是detailColumnInfo标记的一部分。字段/数据的顺序和数量不固定,但目标XML应保持固定。例如。传入数据可以按任意顺序包含10个字段和数据,但目标XML只能有2个字段。为了实现这一点,我相信,在运行时我们必须弄清楚F1字段的顺序,并且必须从dataCells中选择相应的数据。例如。如果F1 is field是detailColumnInfo中的第一个字段,那么我必须从所有dataCells(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时,会出现问题。如果字段值为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>
作为解决方案,我尝试通过更改
中的原始语句在apply-templates中包含空值 <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']"/>
但更改此内容不包含元素<null key="value"/>
。
我是XSLT和XPath的新手,需要帮助才能解决这个问题。
答案 0 :(得分: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>