所以目前网站地图看起来像这样:
但相反,我正在寻找这个:
有没有方便的方法呢?
站点地图代码
...
<url>
<loc>http://mydomain.com</loc>
<changefreq>weekly</changefreq>
<priority>1.00</priority>
</url>
<url>
<loc>http://mydomain.com/category</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url>
...
** XSLT代码**
...
<ul>
<xsl:for-each select="xna:urlset/xna:url">
<li><xsl:value-of select="xna:loc"/></li>
</xsl:for-each>
</ul>
...
答案 0 :(得分:0)
<强>予。这个XSLT 1.0解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kLocByDomain" match="loc"
use="word[1]"/>
<xsl:key name="kLocByDomainAndCat" match="loc"
use="concat(word[1], '+', word[2])"/>
<xsl:key name="kLocByDomainCatProduct" match="loc"
use="concat(word[1], '+', word[2], '+', word[3])"/>
<xsl:template match="/*">
<xsl:variable name="vrtfTokenized">
<urls>
<xsl:apply-templates/>
</urls>
</xsl:variable>
<xsl:apply-templates mode="group"
select="ext:node-set($vrtfTokenized)/*"/>
</xsl:template>
<xsl:template match="/*" mode="group">
<h1>Sitemap</h1>
<ul>
<xsl:apply-templates mode="group" select=
"loc[generate-id()
=
generate-id(key('kLocByDomain', word[1])[1])
]"/>
</ul>
</xsl:template>
<xsl:template match="loc" mode="group">
<li><xsl:value-of select="word[1]"/>
<ul>
<xsl:apply-templates mode="group2" select=
"key('kLocByDomain', word[1])
[generate-id()
=
generate-id(key('kLocByDomainAndCat',
concat(current()/word[1], '+', word[2])
)[1]
)
]"/>
</ul>
</li>
</xsl:template>
<xsl:template match="loc[word[2]]" mode="group2">
<li><xsl:value-of select="word[2]"/>
<ul>
<xsl:apply-templates mode="group3" select=
"key('kLocByDomainAndCat', concat(word[1], '+', word[2]))
[generate-id()
=
generate-id(key('kLocByDomainCatProduct',
concat(current()/word[1],
'+', current()/word[2],
'+', word[3])
)[1]
)
]"/>
</ul>
</li>
</xsl:template>
<xsl:template match="loc[word[3]]" mode="group3">
<li><xsl:value-of select="word[3]"/></li>
</xsl:template>
<xsl:template match="loc">
<loc>
<xsl:call-template name="tokenize">
<xsl:with-param name="pText"
select="substring-after(.,'http://')"/>
</xsl:call-template>
</loc>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="pText"/>
<xsl:if test="string-length($pText)>0">
<word>
<xsl:value-of select=
"substring-before(concat($pText,'/'), '/')"/>
</word>
<xsl:call-template name="tokenize">
<xsl:with-param name="pText" select=
"substring-after($pText,'/')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="text()"/>
<xsl:template match="text()" mode="group2"/>
<xsl:template match="text()" mode="group3"/>
</xsl:stylesheet>
应用于以下XML文档时(基于提供的片段):
<site>
<url>
<loc>http://mydomain.com/</loc>
<changefreq>weekly</changefreq>
<priority>1.00</priority>
</url>
<url>
<loc>http://mydomain.com/category</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
<url>
<loc>http://mydomain.com/category/product1</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
<url>
<loc>http://mydomain.com/category/product2</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
<url>
<loc>http://mydomain.com/other-category/product1</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
<url>
<loc>http://mydomain.com/other-category/product2</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
<url>
<loc>http://mydomain.com/other-category/product3</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
<url>
<loc>http://mydomain2.com/other-category/product3</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url> ...
</site>
生成想要的正确结果:
<h1>Sitemap</h1>
<ul>
<li>mydomain.com
<ul>
<li>category
<ul>
<li>product1</li>
<li>product2</li>
</ul></li>
<li>other-category
<ul>
<li>product1</li>
<li>product2</li>
<li>product3</li>
</ul></li>
</ul></li>
<li>mydomain2.com
<ul>
<li>other-category
<ul>
<li>product3</li>
</ul></li>
</ul></li>
</ul>
-
在浏览器中显示为:
<强>解释强>:
网站地图包含不同的域名,其中包含不同的类别,其中包含不同的产品。
这是一个两遍解决方案。
第一遍标记每个网址。标记由word
元素表示。
第二遍适用于第一遍Muenchian分组的结果,其中包含一个,然后是两个,然后是三个部分。
<强> II。 XSLT 2.0解决方案
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<h1>Sitemap</h1>
<ul>
<xsl:for-each-group select="url/loc"
group-by="tokenize(., '/')[3]"
>
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</ul>
</xsl:template>
<xsl:template match="loc">
<li><xsl:sequence select="tokenize(., '/')[3]"/>
<ul>
<xsl:for-each-group select=
"current-group()[tokenize(., '/')[4]]"
group-by="tokenize(., '/')[4]"
>
<xsl:apply-templates select="." mode="cat"/>
</xsl:for-each-group>
</ul>
</li>
</xsl:template>
<xsl:template match="loc" mode="cat">
<li><xsl:sequence select="tokenize(., '/')[4]"/>
<ul>
<xsl:for-each-group select=
"current-group()[tokenize(., '/')[5]]"
group-by="tokenize(., '/')[5]"
>
<xsl:apply-templates select="." mode="prod"/>
</xsl:for-each-group>
</ul>
</li>
</xsl:template>
<xsl:template match="loc" mode="prod">
<li><xsl:sequence select="tokenize(., '/')[5]"/></li>
</xsl:template>
</xsl:stylesheet>
<强>解释强>
我们使用了许多便于分组的XSLT 2.0功能:
答案 1 :(得分:0)
在此1.0版本中,只使用substring-before
和substring-after
收集转换类别。
要将此转换应用于您的案例,您只需在xsl:param
和xsl:key
内设置真实域名。
请注意,您的输入xml是一个片段,并且您不清楚如何管理命名空间前缀。因此,我在没有命名空间的示例XML上测试了转换。如果源XML包含名称空间前缀,则应调整转换。
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="mydomain" select="'http://mydomain.com/'"/>
<xsl:key name="urlbyloc" match="url" use="substring-before(substring-after(loc,'http://mydomain.com/'),'/')"/>
<xsl:template match="/*">
<ul>
<li><xsl:value-of select="$mydomain"/>
<ul>
<xsl:apply-templates select="url[generate-id()=generate-id(key('urlbyloc', substring-before(substring-after(loc,$mydomain),'/'))[1]) and position()!=1]"/>
</ul>
</li>
</ul>
</xsl:template>
<xsl:template match="url">
<li>
<xsl:value-of select="key('urlbyloc', '')/loc[contains(text(),substring-before(substring-after(current()/loc,$mydomain),'/'))]"/>
<ul>
<xsl:apply-templates select="key('urlbyloc', substring-before(substring-after(loc,$mydomain),'/'))/loc"/>
</ul>
</li>
</xsl:template>
<xsl:template match="loc">
<li><xsl:value-of select="."/></li>
</xsl:template>
<xsl:template match="changefreq|priority"/>
</xsl:stylesheet>
此变换适用于以下输入:
<url-set>
<url>
<loc>http://mydomain.com</loc>
<changefreq>weekly</changefreq>
<priority>1.00</priority>
</url>
<url>
<loc>http://mydomain.com/category</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url>
<url>
<loc>http://mydomain.com/category/prod1</loc>
<changefreq>weekly</changefreq>
<priority>1.00</priority>
</url>
<url>
<loc>http://mydomain.com/category/prod2</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url>
<url>
<loc>http://mydomain.com/othercat</loc>
<changefreq>weekly</changefreq>
<priority>1.00</priority>
</url>
<url>
<loc>http://mydomain.com/othercat/prod1</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url>
<url>
<loc>http://mydomain.com/othercat/prod2</loc>
<changefreq>weekly</changefreq>
<priority>0.80</priority>
</url>
</url-set>
产地:
<ul>
<li>http://mydomain.com/<ul>
<li>http://mydomain.com/category<ul>
<li>http://mydomain.com/category/prod1</li>
<li>http://mydomain.com/category/prod2</li>
</ul>
</li>
<li>http://mydomain.com/othercat<ul>
<li>http://mydomain.com/othercat/prod1</li>
<li>http://mydomain.com/othercat/prod2</li>
</ul>
</li>
</ul>
</li>
</ul>
使用XSLT 2.0用户定义函数,我们可以使转换更具可读性。此外,您需要在初始参数中指明您的域名,因为2.0 xsl:key
支持变量引用。
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:empo="http://stackoverflow.com/users/253811/empo"
exclude-result-prefixes="empo">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="mydomain" select="'http://mydomain.com/'"/>
<xsl:function name="empo:get-category">
<xsl:param name="loc"/>
<xsl:param name="mydomain"/>
<xsl:value-of select="substring-before(substring-after($loc,$mydomain),'/')"/>
</xsl:function>
<xsl:key name="urlbyloc" match="url" use="empo:get-category(loc,$mydomain)"/>
<xsl:template match="/*">
<ul>
<li><xsl:value-of select="$mydomain"/>
<ul>
<xsl:apply-templates select="url[generate-id()=generate-id(key('urlbyloc', empo:get-category(loc,$mydomain))[1]) and position()!=1]"/>
</ul>
</li>
</ul>
</xsl:template>
<xsl:template match="url">
<li>
<xsl:value-of select="key('urlbyloc', '')/loc[contains(text(),empo:get-category(current()/loc,$mydomain))]"/>
<ul>
<xsl:apply-templates select="key('urlbyloc',empo:get-category(loc,$mydomain))/loc"/>
</ul>
</li>
</xsl:template>
<xsl:template match="loc">
<li><xsl:value-of select="."/></li>
</xsl:template>
<xsl:template match="changefreq|priority"/>
</xsl:stylesheet>
答案 2 :(得分:0)
这是一个应该做你需要的简单模板:
<xsl:template match="/">
<xsl:apply-templates select="//url[1]" />
</xsl:template>
<xsl:template match="url">
<xsl:param name="prefix" />
<ul>
<li><xsl:value-of select="substring-after(loc,$prefix)" /></li>
<xsl:apply-templates select="../url[substring-after(loc,current()/loc) and not(contains(substring(substring-after(loc,current()/loc),2),'/'))]">
<xsl:with-param name="prefix" select="concat(loc,'/')" />
</xsl:apply-templates>
</ul>
</xsl:template>
第一个模板只是选择你的起点;在这种情况下,假设文档中的第一个URL包含您的根。在这里使用你需要的任何xpath; //url[loc='http://mydomain.com']
也会这样做。
第二个模板完成工作,只需输出当前的loc
字段,使用substring-after剥离之前的字段。然后,它会将自身应用于url
字段以当前文本中的文本开头但没有任何其他loc
个字符的任何其他/
个节点。