我必须使用XML数据源并将其转换为json,展平,以便我没有json对象。我有事情工作,除了多次出现的元素,我多次出现。我理解为什么使用apply-templates命令会发生这种情况,我只是不确定如何修复它。
原始XML如下所示:
<entry>
<id>542345255</id>
<published>2013-10-15T15:30:02Z</published>
<link rel="alternate" type="text/html" href="http://test.com"/>
<link rel="self" type="application/json" href="http://test1.com"/>
</entry>
期望的结果将是:
{
"id" : "542345255",
"published" : "2013-10-15T15:30:02Z",
"link_rel" : "[alternate, self]",
"link_type" : "[text/html, application/json]",
"link_href" : "[http://test.com, http://test1.com]"
}
我的XSLT是:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:variable name="links" select="entry/link"/>
<xsl:template match="entry">
<xsl:text>{</xsl:text>
<xsl:apply-templates/>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="id">
<xsl:text>"id" : "</xsl:text>
<xsl:value-of select="."/>
<xsl:text>", </xsl:text>
</xsl:template>
<xsl:template match="published">
<xsl:text>"postedTime" : "</xsl:text>
<xsl:value-of select="."/>
<xsl:text>", </xsl:text>
</xsl:template>
<xsl:template match="link">
<xsl:text>"link_rel" : "[</xsl:text>
<xsl:for-each select="$links">
<xsl:value-of select="./@rel"/>
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
<xsl:text>]", </xsl:text>
<xsl:text>"link_type" : "[</xsl:text>
<xsl:for-each select="$links">
<xsl:value-of select="./@type"/>
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
<xsl:text>]", </xsl:text>
<xsl:text>"link_href" : "[</xsl:text>
<xsl:for-each select="$links">
<xsl:value-of select="./@href"/>
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
<xsl:text>]", </xsl:text>
</xsl:template>
</xsl:stylesheet>
有了这个,我得到的结果是:
{
"id" : "542345255",
"published" : "2013-10-15T15:30:02Z",
"link_rel" : "[alternate, self]",
"link_type" : "[text/html, application/json]",
"link_href" : "[http://test.com, http://test1.com]"
"link_rel" : "[alternate, self]",
"link_type" : "[text/html, application/json]",
"link_href" : "[http://test.com, http://test1.com]"
}
答案 0 :(得分:1)
由于输入元素和输出元素之间没有一对一的关系,您可能需要调用特定模板,以便同时处理所有link
元素。尝试:
<xsl:template match="entry">
<xsl:text>{</xsl:text>
<xsl:apply-templates/>
<xsl:call-template name="link" />
<xsl:text>}</xsl:text>
</xsl:template>
然后代替
<xsl:template match="link">
使用
<xsl:template name="link">
答案 1 :(得分:1)
您可以使用xsl:for-each-group
做一些更通用的事情。 (您的示例XSLT是2.0。)
示例...
XML输入
<entry>
<id>542345255</id>
<published>2013-10-15T15:30:02Z</published>
<link rel="alternate" type="text/html" href="http://test.com"/>
<link rel="self" type="application/json" href="http://test1.com"/>
</entry>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:text>{
</xsl:text>
<xsl:for-each-group select="*[text()]" group-by="name()">
<xsl:call-template name="json">
<xsl:with-param name="name" select="name()"/>
</xsl:call-template>
</xsl:for-each-group>
<xsl:for-each-group select="*/@*" group-by="concat(../name(),name())">
<xsl:call-template name="json">
<xsl:with-param name="name" select="concat(../name(),'_',name())"/>
</xsl:call-template>
</xsl:for-each-group>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="*[text()]" mode="json">
<xsl:value-of select="concat('"',name(),'"',' : "',.,'"
')"/>
</xsl:template>
<xsl:template name="json">
<xsl:param name="name"/>
<xsl:value-of select="concat('	"',$name,'"',' : "')"/>
<xsl:if test="count(current-group())>1">
<xsl:text>[</xsl:text>
</xsl:if>
<xsl:value-of select="current-group()" separator=", "/>
<xsl:if test="count(current-group())>1">
<xsl:text>]</xsl:text>
</xsl:if>
<xsl:text>"</xsl:text>
<xsl:if test="(self::* and (//@*)[1]) or not(last()=position())">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
{
"id" : "542345255",
"published" : "2013-10-15T15:30:02Z",
"link_rel" : "[alternate, self]",
"link_type" : "[text/html, application/json]",
"link_href" : "[http://test.com, http://test1.com]"
}
答案 2 :(得分:0)
我认为@ Klazen108有正确的想法,所以这就是你的XSL的样子:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="entry">
<xsl:text>{</xsl:text>
<xsl:value-of select="concat('"id" : "', ./id, '"')" /><xsl:text>, </xsl:text>
<xsl:value-of select="concat('"postedTime" : "', ./published, '"')" /><xsl:text>, </xsl:text>
<xsl:call-template name="link_rel" /><xsl:text>, </xsl:text>
<xsl:call-template name="link_href" /><xsl:text>, </xsl:text>
<xsl:call-template name="link_type" />
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template name="link_rel">
<xsl:text>"link_rel" : [</xsl:text>
<xsl:for-each select="./link">
<xsl:value-of select="concat('"', ./@rel, '"')" />
<xsl:if test="position()!=last()"><xsl:text>, </xsl:text></xsl:if>
</xsl:for-each>
<xsl:text>]</xsl:text>
</xsl:template>
<xsl:template name="link_type">
<xsl:text>"link_type" : [</xsl:text>
<xsl:for-each select="./link">
<xsl:value-of select="concat('"', ./@type, '"')" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
<xsl:text>], </xsl:text>
</xsl:template>
<xsl:template name="link_href">
<xsl:text>"link_href" : [</xsl:text>
<xsl:for-each select="./link">
<xsl:value-of select="concat('"', ./@href, '"')" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
<xsl:text>], </xsl:text>
</xsl:template>
</xsl:stylesheet>