CSV到XML hreflang网站地图



我是bash和脚本的新手,非常感谢您的帮助。

我正在尝试从csv输入生成一个XML文件,以最终形成一个18nXML站点地图。

我的CSV结构如下

iso语言列标题

en,de,fr

en url,de ulr,fr url

en-url2、de-url2、fr-url2

我想将csv输出为XML站点地图格式:

<url>
<loc>http://www.example.com/english/page.html</loc>             #first column (second line)
<xhtml:link 
rel="alternate"
hreflang="de"                                        #second column iso value (first line)
href="http://www.example.com/deutsch/page.html"/>    #second column URL (second line)
<xhtml:link 
rel="alternate"
hreflang="fr"                                       #third column iso value (first line)   
href="http://www.example.com/french/page.html"/>    #third column URL (second line)  
</url>

然后,它将遍历第一列中的所有值,以生成完整的站点地图。

我拼凑的脚本没有为我提供预期的输出,而且我在努力控制数组中的值/回显值时有点卡住了。

我的脚本当前输出以下

<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>en</loc> 
<xhtml:link rel="alternate" hreflang="en" href="fr"
<xhtml:link rel="alternate" hreflang="en" href="fr"
<xhtml:link rel="alternate" hreflang="en" href="fr"
</url>
<url>
<loc>example.com</loc> 
<xhtml:link rel="alternate" hreflang="example.com" href="example.fr"
<xhtml:link rel="alternate" hreflang="example.com" href="example.fr"
<xhtml:link rel="alternate" hreflang="example.com" href="example.fr"
</url>

我的脚本

`#!/bin/bash
file_in="sample.csv"
file_out="sample.xml"
echo '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">' > $file_out
while IFS=$',' read -r -a arry
do
echo '  <url>' >> $file_out
echo '    <loc>'${arry[0]}'</loc> '>> $file_out
for u in "${arry[@]}"
do
echo '<xhtml:link rel="alternate" hreflang="'${arry[0]}'" href="'${arry[2]}'"'>> $file_out
done
echo '  </url>' >> $file_out
done < $file_in
echo '</urlset>' >> $file_out`

简而言之,脚本是从数组的索引中而不是列中回显元素。此外,hreflang值需要从循环中转义,以便它在hreflang="中保持为常量"输出中的值。

如果有人告诉我如何将列存储为单独的数组,或者如何在csv列中迭代高估值,这将非常有用。

非常感谢!

考虑对脚本进行一个小的更改。它将捕获数组中的列标题,使处理更容易。

代码假定input.csv为

en,de,fr
en-url,de-ulr,fr-url
en-url2,de-url2,fr-url2

脚本(请参阅下面关于重定向的说明(。

#!/bin/bash
# Redirect input and output
file_in="sample.csv"
file_out="sample.xml"
exec < $file_in >$file_out
# XML Header
echo '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">'
# Read column headers into langs
IFS=$, read -r -a langs
# number of alternate languages
n_langs=${#langs[@]}
# Loop over data
# Read line of URLs
while IFS=$',' read -r -a urls
do
echo "  <url>"
echo "    <loc>${urls[0]}</loc> "
# Loop of alternative languages
for ((lx=1 ; lx<n_langs ; lx++)) ; do
echo "    <xhtml:link rel="alternate" hreflang='${langs[lx]}' href='${urls[lx]}' />"
done
echo "  </url>"
done
echo "</urlset>"

注:

  • 脚本对XML属性使用单引号。这简化了对bash脚本的引用
  • 对脚本输入/输出进行参数化是很常见的。与其对输入和输出进行硬编码,不如考虑删除前3行(file_in=…through exec(,并通过重定向调用脚本:script.sh < sample.csv > sample.xml

如果你想创建一个XML文件,那么我肯定会为这项工作使用合适的工具。

因为Bash不懂XML,所以我推荐像xidel这样的工具。

我假设">input.csv":

en,de,fr
http://www.example.com/english/page.html,http://www.example.com/deutsch/page.html,http://www.example.com/french/page.html

1.将csv文件转换为一系列";转置的";序列

$ xidel -s input.csv -e 'x:lines($raw) ! array{tokenize(.,",")}'
["en", "de", "fr"]
["http://www.example.com/english/page.html", "http://www.example.com/deutsch/page.html", "http://www.example.com/french/page.html"]
$ xidel -s input.csv -e '
let $ln:=x:lines($raw) ! array{tokenize(.,",")} return
(1 to count($ln[1]())) ! join($ln(.))
'
en http://www.example.com/english/page.html
de http://www.example.com/deutsch/page.html
fr http://www.example.com/french/page.html
$ xidel -s input.csv -e '
let $ln:=x:lines($raw) ! array{tokenize(.,",")} return
(2 to count($ln[1]())) ! join($ln(.))
'
de http://www.example.com/deutsch/page.html
fr http://www.example.com/french/page.html

2.将这些序列转换为XML

xidel -s input.csv -e '
let $ln:=x:lines($raw) ! array{tokenize(.,",")} return
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="https://www.w3.org/1999/xhtml">
<url>
<loc>{$ln[2](1)}</loc>
{(2 to count($ln[1]())) ! <xhtml:link rel="alternate" hreflang="{$ln(.)[1]}" href="{$ln(.)[2]}"/>}
</url>
</urlset>
' --output-format=xml --output-node-indent --output-declaration='<?xml version="1.0" encoding="UTF-8"?>'
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="https://www.w3.org/1999/xhtml">
<url>
<loc>http://www.example.com/english/page.html</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://www.example.com/deutsch/page.html"/>
<xhtml:link rel="alternate" hreflang="fr" href="http://www.example.com/french/page.html"/>
</url>
</urlset>

(如果您的shell已经设置为UTF-8,那么--output-declaration是可选的(

最新更新