使用键匹配

时间:2016-08-06 11:17:04

标签: xml xslt

我有一个像这样的xml,

<categories>
    <data>
        <category_id>216</category_id>
        <children_sort_order>217</children_sort_order>
        <children_sort_order>324</children_sort_order>
        <children_sort_order>395</children_sort_order>
        <children_sort_order>580</children_sort_order>
        <children_sort_order>506</children_sort_order>
        <children_sort_order>466</children_sort_order>
        <children_sort_order>626</children_sort_order>
        <children_sort_order>532</children_sort_order>
        <depth>0</depth>
        <description/>
        <name>Products</name>
        <path>products</path>
        <slug>products</slug>
        <state>live</state>
        <status>
            <state>live</state>
        </status>
        <updated_at>2016-06-09T05:13:08Z</updated_at>
        <westfield_locale>en_AU</westfield_locale>
        <sort_order>0</sort_order>
    </data>
    <data>
        <category_id>217</category_id>
        <children_sort_order>218</children_sort_order>
        <children_sort_order>319</children_sort_order>
        <children_sort_order>232</children_sort_order>
        <children_sort_order>237</children_sort_order>
        <children_sort_order>244</children_sort_order>
        <children_sort_order>255</children_sort_order>
        <children_sort_order>225</children_sort_order>
        <children_sort_order>307</children_sort_order>
        <children_sort_order>286</children_sort_order>
        <children_sort_order>262</children_sort_order>
        <children_sort_order>269</children_sort_order>
        <children_sort_order>279</children_sort_order>
        <children_sort_order>251</children_sort_order>
        <children_sort_order>299</children_sort_order>
        <children_sort_order>292</children_sort_order>
        <depth>1</depth>
        <description/>
    <name>Women's</name>
        <path>products/womens-fashion-accessories</path>
        <slug>womens-fashion-accessories</slug>
        <state>live</state>
        <status>
            <state>live</state>
        </status>
        <updated_at>2016-07-12T03:35:17Z</updated_at>
        <westfield_locale>en_AU</westfield_locale>
        <sort_order>0</sort_order>
    </data>
    <errors />
    <meta>
        <api_version>1.3</api_version>
        <deprecation_information />
    </meta>
</categories>

我想阅读顶级元素并生成父xml元素,然后读取相关类别并作为子元素插入第一个元素。所以输出应该是这样的

<Category category_id="216" name="Products" parent="0">
  <Category category_id="217" name="Women's" parent="216">
  </Category>
</Category> 

我尝试使用密钥匹配来应用递归模板,但这不起作用。

<xsl:key name="children-search" match="data" use="category_id"/>
    <xsl:template name="Category">
            <xsl:param name="parent"/>

            <xsl:variable name="current" select="category_id"/>

            <xsl:element name="Category">
                <xsl:attribute name="id"><xsl:value-of select="category_id"/></xsl:attribute>
                <xsl:attribute name="code">1</xsl:attribute><!--<xsl:value-of select="sort_order"/></xsl:attribute>--><!-- Field is no longer provided in the Westfield Category Data -->
                <xsl:attribute name="name"><xsl:value-of select="slug"/></xsl:attribute>
                <xsl:attribute name="displayname"><xsl:value-of select="name"/></xsl:attribute>
                <xsl:attribute name="desc"><xsl:value-of select="description"/></xsl:attribute>
                <xsl:attribute name="ismappable">1</xsl:attribute> <!-- Field is no longer provided in the Westfield Category Data -->
                <xsl:attribute name="order"><xsl:value-of select="sort_order"/></xsl:attribute>
                <xsl:attribute name="active"><xsl:choose><xsl:when test="state = 'live'">1</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:attribute>
                <xsl:attribute name="parent"><xsl:value-of select="$parent"/></xsl:attribute>
            </xsl:element>

            <!-- recursive call -->
            <xsl:for-each select="children_sort_order">
                <xsl:call-template name="Category"><xsl:with-param name="parent" select="key('children-search', $current)"/></xsl:call-template>
            </xsl:for-each>
        </xsl:template> 

请告诉我是否有更好的方法来解决这个问题。非常感谢

1 个答案:

答案 0 :(得分:1)

此处不需要带参数的命名模板。相反,如果您有一个匹配data的模板,那么您可以像这样获取子元素:

<xsl:for-each select="children_sort_ordesr">
   <xsl:apply-templates select="key('children-search', .)" />
</xsl:for-each>

或者更好(感谢Martin Honnen!)这个..

 <xsl:apply-templates select="key('children-search', children_sort_order)" />

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="children-search" match="data" use="category_id"/>
<xsl:key name="parent_search" match="children_sort_order" use="."/>

 <xsl:template match="categories">
    <xsl:copy>
       <xsl:apply-templates select="data[not(key('parent_search', category_id))]" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="data">
     <Category id="{category_id}" name="{name}">
       <!-- recursive call -->
       <xsl:apply-templates select="key('children-search', children_sort_order)" />
     </Category>
   </xsl:template>
</xsl:stylesheet>

请注意使用“parent_search”键,该键仅用于选择顶级data元素(即没有父元素的data元素)。如果顶级<xsl:apply-templates select="data[1]" />元素始终是XML中的第一个data元素,则可以将其简化为data

另请注意使用Attribute Value TemplatesCategory元素上创建属性,这极大地简化了XSLT。