3

我必须获取 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]"
}
4

3 回答 3

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">
于 2013-10-17T20:01:42.173 回答
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>{&#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]"
}
于 2013-10-18T01:55:11.860 回答
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>
于 2013-10-17T21:16:37.630 回答