2013-10-17 80 views
3

我必須採取XML數據饋送並將其轉換爲json,展平,以便我沒有json對象。除了多次出現的元素外,我的工作都有效,我得到了多次出現。我明白爲什麼apply-templates命令發生這種情況,我不知道如何解決這個問題。XSLT過程第一次出現元素

原始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]" 
} 
+1

http://www.bramstein.com/projects/xsltjson/conf/xml-to-jsonml.xsl – Wrikken

回答

1

你可以做點更多的東西ic通過使用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>{&#xA;</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('&quot;',name(),'&quot;',' : &quot;',.,'&quot;&#xA;')"/> 
    </xsl:template> 

    <xsl:template name="json"> 
     <xsl:param name="name"/> 
     <xsl:value-of select="concat('&#x9;&quot;',$name,'&quot;',' : &quot;')"/> 
     <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>&quot;</xsl:text> 
     <xsl:if test="(self::* and (//@*)[1]) or not(last()=position())"> 
      <xsl:text>,</xsl:text> 
     </xsl:if> 
     <xsl:text>&#xA;</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]" 
} 
1

由於輸入元素和輸出元素之間沒有1對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"> 
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('&quot;id&quot; : &quot;', ./id, '&quot;')" /><xsl:text>, </xsl:text> 
     <xsl:value-of select="concat('&quot;postedTime&quot; : &quot;', ./published, '&quot;')" /><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('&quot;', ./@rel, '&quot;')" /> 
      <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('&quot;', ./@type, '&quot;')" /> 
      <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('&quot;', ./@href, '&quot;')" /> 
      <xsl:if test="position()!=last()">, </xsl:if> 
     </xsl:for-each> 
     <xsl:text>], </xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 
相關問題