如何在XSLT映射中从含嵌套结构的JSON对象提取Name字段值
问题描述
我有如下JSON文件,需要用XSLT提取其中的"Name"字段值。移除test块时代码可正常运行,但保留test块时返回空结果。
sample.json
{ "books": [ { "test": { "count": 1 }, "Name": "C", "Type": "String" }, { "test": { "count": 2 }, "Name": "C++", "Type": "String" } ] }
我尝试的XSLT代码如下:
sample.xslt
<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://www.example.com/mf" exclude-result-prefixes="#all" expand-text="yes"> <xsl:output method="json" indent="yes"/> <xsl:function name="mf:apply-templates" as="item()*"> <xsl:param name="items" as="item()*"/> <xsl:apply-templates select="$items"/> </xsl:function> <xsl:template match="." name="xsl:initial-template"> <xsl:sequence select="array { mf:apply-templates(?books?*) }"/> </xsl:template> <xsl:template match=".[. instance of map(xs:string, xs:anyAtomicType)]"> <xsl:map> <xsl:map-entry key="'resourceType'" select="'Test'"/> <xsl:map-entry key="'identifier'"> <xsl:map> <xsl:map-entry key="'name'" select="?Name" /> </xsl:map> </xsl:map-entry> </xsl:map> </xsl:template> </xsl:stylesheet>
期望输出:
output.json
[ { "resourceType": "Test", "identifier": { "name":"C" } }, { "resourceType": "Test", "identifier": { "name":"C++" } } ]
问题原因
你的模板匹配条件.[. instance of map(xs:string, xs:anyAtomicType)]要求map的所有值都是原子类型(xs:anyAtomicType),但test字段的值是一个嵌套map,不符合这个类型约束,因此该模板不会被触发,导致返回空结果。
解决方案
修改模板的匹配条件,改为匹配任意类型的map即可:
<xsl:template match="map()"> <xsl:map> <xsl:map-entry key="'resourceType'" select="'Test'"/> <xsl:map-entry key="'identifier'"> <xsl:map> <xsl:map-entry key="'name'" select="?Name" /> </xsl:map> </xsl:map-entry> </xsl:map> </xsl:template>
或者也可以把原来的匹配条件调整为.[. instance of map(*)],效果一致,都能匹配包含嵌套map的对象。
修改后的完整XSLT代码:
修正后的sample.xslt
<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://www.example.com/mf" exclude-result-prefixes="#all" expand-text="yes"> <xsl:output method="json" indent="yes"/> <xsl:function name="mf:apply-templates" as="item()*"> <xsl:param name="items" as="item()*"/> <xsl:apply-templates select="$items"/> </xsl:function> <xsl:template match="." name="xsl:initial-template"> <xsl:sequence select="array { mf:apply-templates(?books?*) }"/> </xsl:template> <xsl:template match="map()"> <xsl:map> <xsl:map-entry key="'resourceType'" select="'Test'"/> <xsl:map-entry key="'identifier'"> <xsl:map> <xsl:map-entry key="'name'" select="?Name" /> </xsl:map> </xsl:map-entry> </xsl:map> </xsl:template> </xsl:stylesheet>
运行这段代码就能得到你期望的输出结果。
内容的提问来源于stack exchange,提问作者Sujit Kumar
相关产品推荐
相关产品推荐

