XSLT: regex提取并创建嵌套节点



在我所有的谷歌搜索中,我似乎找不到这是如何做到的(加上我是xslt的新手)。我试图采取一个平面sitemap.xml文件,并有嵌套的孩子,如果url路径规定。

示例站点地图

<sitemap>
<url>
<loc>https://example.com/</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://example.com/athletics/index.html</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://example.com/athletics/colleges-schools.html</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://example.com/training/index.html</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<urls>....</urls>
</sitemap>

我要么想最终得到这样的东西

<sitemap>
<url>
<loc>https://example.com/</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
<children>
<url>
<loc>https://example.com/athletics/index.html</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
<children>
<url>
<loc>https://example.com/athletics/colleges-schools.html</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
</children>
</url>
<url>
<loc>https://example.com/training/index.html</loc>
<lastmod>2022-02-28</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
</children>
</url>
</sitemap>

或转换为.json,但我已经学会了如何很容易地将xml转换为json,所以我只是真的需要了解如何将regex(或其他东西)转换为<loc>字段并基于/XX_name_XX/

生成子

查找" xslt递归分组";可能会给你一些启发。

使用XSLT 2.0或3.0肯定会容易得多,它们内置了对正则表达式处理、标记化和分组的支持。

话虽如此,它仍然具有挑战性,我不建议您第一次尝试XSLT编程。但是说"如果我是你,我不会从这里开始"并不是很有用。

一般的方法是你想要对前N个令牌中相同的URL进行分组(其中令牌来自于用斜杠分隔URL);并且在每个这样的组中,您希望通过递归调用将其划分为在前N+1个令牌中相同的子组。它看起来像这样:

<xsl:function name="f:grouping-key" as="xs:string">
<xsl:param name="url" as="xs:string"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:sequence select="tokenize($url, '/') 
=> subsequence(1, $level)
=> string-join('/')"/>
</xsl:function>
<xsl:function name="f:group-urls">
<xsl:param name="urls" as="element(url)*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$urls"
group-by="f:grouping-key(loc, $level)">
<xsl:choose>
<xsl:when test="count(current-group()) = 1">
<xsl:copy-of select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<url>
<loc>{current-grouping-key()}</loc>
<xsl:copy-of select="lastmod, changefreq, priority"/>
<children>
<xsl:sequence select="f:group-urls(current-group(), $level+1"/>
</children>
</url>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>

然后你通过呼叫f:group-urls(//url, 1)来启动它。

不测试。

最新更新