В этих категориях преобразования 1.0 собираются только с помощью substring-before
и substring-after
.
Чтобы применить это преобразование к вашему случаю, вам просто нужно установить свой реальный домен в xsl:param
и в xsl:key
.
Обратите внимание, что ваш входной xml является фрагментом, и неясно, как вам нужен управляемый префикс пространства имен. Поэтому я проверил преобразование на примере XML без пространств имен. Если ваш исходный XML содержит префиксы пространства имен, преобразование должно быть настроено.
XSLT 1.0 протестировано под Saxon 6.5.5
<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 протестировано под Saxon-B 9.0.0.4J
<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>