求助:编写XSLT代码统计XML中出现次数最多的Journal_Name及浏览器XML/XSL自动样式支持问题
解答你的XSLT问题
一、找到出现次数最多的Journal_Name
先看你写的XSLT代码,有几个关键问题需要修正:
@Journal_Name是引用属性的写法,但你的XML里Journal_Name是子元素不是属性,所以要去掉@符号,用Journal_Name来引用;- 直接遍历所有
row再排序的方式会重复处理相同的期刊名称,最好用分组统计的方式来实现,更高效也更准确。
针对XSLT 1.0(兼容性最广的版本),可以用Muenchian分组法来完成统计,这是XSLT1.0里处理分组的标准方案。下面是完整的可运行示例:
示例XML文件(含多条测试数据)
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="journal-stats.xsl"?> <Bibliography> <row> <Title>Title-B-0</Title> <Author>Jason Adair</Author> <Year>2015</Year> <Publication_Name>ACM</Publication_Name> <DOI>533/49</DOI> <Date>6/2/2021</Date> <Journal_Name>journal-s</Journal_Name> <Journal_Volume>9</Journal_Volume> <Journal_Issue>8</Journal_Issue> <Conference_Name></Conference_Name> <Conference_Location></Conference_Location> <Book_Title></Book_Title> <Book_Editor></Book_Editor> </row> <row> <Title>Title-A-1</Title> <Author>Jane Doe</Author> <Year>2020</Year> <Publication_Name>IEEE</Publication_Name> <DOI>123/45</DOI> <Date>1/3/2022</Date> <Journal_Name>journal-s</Journal_Name> <Journal_Volume>10</Journal_Volume> <Journal_Issue>2</Journal_Issue> <Conference_Name></Conference_Name> <Conference_Location></Conference_Location> <Book_Title></Book_Title> <Book_Editor></Book_Editor> </row> <row> <Title>Title-C-2</Title> <Author>John Smith</Author> <Year>2018</Year> <Publication_Name>Elsevier</Publication_Name> <DOI>789/01</DOI> <Date>4/5/2021</Date> <Journal_Name>journal-a</Journal_Name> <Journal_Volume>5</Journal_Volume> <Journal_Issue>3</Journal_Issue> <Conference_Name></Conference_Name> <Conference_Location></Conference_Location> <Book_Title></Book_Title> <Book_Editor></Book_Editor> </row> </Bibliography>
对应的XSLT文件(命名为journal-stats.xsl)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义分组规则:按Journal_Name的值对row元素分组 --> <xsl:key name="journal-group" match="row" use="Journal_Name"/> <xsl:template match="/"> <html> <body> <h3>出现次数最多的期刊</h3> <!-- 遍历每个唯一的期刊分组(只处理每个分组的第一个元素) --> <xsl:for-each select="Bibliography/row[generate-id() = generate-id(key('journal-group', Journal_Name)[1])]"> <!-- 按分组的元素数量(期刊出现次数)降序排序 --> <xsl:sort select="count(key('journal-group', Journal_Name))" order="descending"/> <!-- 只取排序后的第一个结果(即次数最多的期刊) --> <xsl:if test="position() = 1"> <p>期刊名称: <strong><xsl:value-of select="Journal_Name"/></strong></p> <p>出现次数: <xsl:value-of select="count(key('journal-group', Journal_Name))"/></p> </xsl:if> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>
代码逻辑说明:
- 用
<xsl:key>定义分组规则,把所有row元素按Journal_Name的值归类; - 通过
generate-id()判断每个分组的第一个元素,确保每个期刊只被统计一次; - 按每个分组的元素数量(即期刊出现次数)降序排序,取第一个结果就是出现次数最多的期刊。
如果你的XSLT处理器支持2.0及以上版本,还可以用更简洁的for-each-group指令,但1.0的写法兼容性更强,适合新手入门。
二、浏览器不自动应用XSL的问题
新版浏览器确实对XML+XSL的本地加载做了限制,主要是出于安全考量,常见原因和解决方法如下:
- 缺少XSL声明:必须在XML的
<?xml?>声明之后、根元素之前添加XSL引用,格式如下:
注意<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="your-style.xsl"?> <Bibliography>...</Bibliography>href要正确指向你的XSL文件路径(如果XML和XSL在同一文件夹,直接写文件名即可)。 - 本地文件跨域限制:Chrome、Edge等Chromium内核浏览器默认禁止本地XML加载本地XSL文件,解决方法:
- 用本地服务器打开文件:比如用Python运行
python -m http.server,或者Node.js的http-server工具,然后在浏览器里访问http://localhost:8000/你的XML文件名.xml; - 临时启动浏览器时添加参数(不推荐长期使用):比如Chrome可以用
chrome.exe --allow-file-access-from-files启动,允许本地文件之间的访问。
- 用本地服务器打开文件:比如用Python运行
- 浏览器支持变化:主流浏览器(Chrome、Firefox、Edge)仍然支持XSLT 1.0,只是对本地文件的安全限制更严格了,通过服务器加载就能正常使用。
内容的提问来源于stack exchange,提问作者mmmmmmmmm
相关产品推荐
相关产品推荐

