我试图将两个单独的XML文件合并为一个HTML文件,并使用XSL。我从第一个XML中得到了正确的东西,但当我从第二个XML中尝试同样的东西时,我要么在一行中得到所有单词,要么只在第一行中得到好几次。
XML1
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="xsltcss.css"?>
<?xml-stylesheet type="text/xsl" href="xslt.xsl" ?>
<lexicon>
<head>
<title>Danish</title>
<author>Mattias Liljegren</author>
</head>
<language value="danish">
<word value="dog">hund</word>
<word value="coffee">kaffe</word>
<word value="tree">træ</word>
<word value="chair">stol</word>
<word value="flashlight">lommelygte</word>
<word value="cat">kat</word>
<word value="fish">fisk</word>
<word value="car">bil</word>
<word value="phone">telefon</word>
<word value="forest">skov</word>
</language>
</lexicon>
XML2
<?xml version="1.0" encoding="UTF-8"?>
<lexicon>
<head>
<title>Croatian</title>
<author>Mattias Liljegren</author>
</head>
<language value="croatian">
<word value="dog">pas</word>
<word value="coffee">kava</word>
<word value="tree">drvo</word>
<word value="chair">stolica</word>
<word value="flashlight">baterija</word>
<word value="cat">mačka</word>
<word value="fish">riba</word>
<word value="car">automobil</word>
<word value="phone">telefon</word>
<word value="forest">šuma</word>
</language>
</lexicon>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<html>
<head>
<link rel="stylesheet" type="text/css" href="xsltcss.css" />
</head>
<body>
<xsl:for-each select="lexicon/head/title">
<p>
<xsl:value-of select="." />
</p>
<p>
<xsl:value-of select="document('kroatiska.xml')/lexicon/head/title/." />
</p>
</xsl:for-each>
<xsl:for-each select="lexicon/language/word">
<p>
<xsl:value-of select="." />
</p>
</xsl:for-each>
<xsl:for-each select="lexicon/language/word">
<p>
<xsl:value-of select="document('kroatiska.xml')/lexicon/language/word" />
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
两个单独的xml文件,我想要每个文件中的第一个单词,然后是第二个单词,依此类推。Atm我从原始xml中得到了正确的单词,但只从第二个xml文件中得到了第一个单词"pas"。
预期结果:
Danish
hund
kaffe
trä
stol
lommelygte
kat
fisk
bil
telefon
skov
Croatian
pas
kava
drvo
stolica
baterija
macka
riba
automobil
telefon
suma
我想你应该把这两个列表放在一起,就像在字典里一样。要获得两个单独列表的显示结果是相当琐碎的:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/lexicon">
<html>
<body>
<!-- this document -->
<h3>
<xsl:value-of select="language/@value"/>
</h3>
<xsl:for-each select="language/word">
<p>
<xsl:value-of select="."/>
</p>
</xsl:for-each>
<!-- external document -->
<xsl:variable name="kroatiska" select="document('kroatiska.xml')/lexicon" />
<h3>
<xsl:value-of select="$kroatiska/language/@value"/>
</h3>
<xsl:for-each select="$kroatiska//language/word">
<p>
<xsl:value-of select="."/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
根据引人入胜的XSLT讨论对于循环与应用模板,请考虑一个替代版本以避免多次<xsl:for-each>
调用。根据XSLT大师(@Tomalak、@DimitreNovatchev、@MichaelKay(的建议:
-
使用
for-each
会使程序变得更复杂添加嵌套级别,重用代码也是不可能的每个块的内部。使用apply-templates
将(完成时右(生成更灵活、更模块化的XSLT。 -
使用
<xsl:template>
和<xsl:apply-templates>
更强大、更优雅。。。xsl:apply-templates
比xsl:for-each
丰富和深入得多,即使只是因为我们不知道将在选择的节点上应用什么代码——在一般情况下,节点列表的不同节点的代码也会不同。 -
xsl:apply-templates
相对于for-each
的主要优势在于,代码能够更好地适应不断变化的文档结构和不断变化的处理要求。
在您的情况下,由于您需要遍历外部文档中的节点,xsl:for-each
是不可避免的:
XSLT
(使用lexicon
、language
和word
模板(
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/lexicon">
<html>
<head>
<link rel="stylesheet" type="text/css" href="xsltcss.css" />
</head>
<xsl:apply-templates select="language" />
</html>
</xsl:template>
<xsl:template match="language">
<body>
<xsl:variable name="other_doc" select="document('kroatiska.xml')" />
<h3>
<xsl:value-of select="@value"/>
</h3>
<xsl:apply-templates select="word" />
<h3>
<xsl:value-of select="$other_doc/lexicon/language/@value" />
</h3>
<xsl:for-each select="$other_doc/lexicon/language/word">
<p>
<xsl:value-of select="text()" />
</p>
</xsl:for-each>
</body>
</xsl:template>
<xsl:template match="word">
<p>
<xsl:value-of select="text()" />
</p>
</xsl:template>
</xsl:stylesheet>
HTML
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="xsltcss.css">
</head>
<body>
<h3>danish</h3>
<p>hund</p>
<p>kaffe</p>
<p>træ</p>
<p>stol</p>
<p>lommelygte</p>
<p>kat</p>
<p>fisk</p>
<p>bil</p>
<p>telefon</p>
<p>skov</p>
<h3>croatian</h3>
<p>pas</p>
<p>kava</p>
<p>drvo</p>
<p>stolica</p>
<p>baterija</p>
<p>mačka</p>
<p>riba</p>
<p>automobil</p>
<p>telefon</p>
<p>šuma</p>
</body>
</html>
这是Parfait回答后注释的扩展。
Parfait在回答中说:
在您的情况下,由于您需要遍历外部文档中的节点,
xsl:for-each
是不可避免的:
在一条评论中,我问为什么会这样,Parfait回答说:
如果你能展示如何通过
document()
避免节点上的xsl:for-each
,我很感兴趣!
下面的样式表显示了如何仅使用apply-templates
:获得相同的结果
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/lexicon">
<html>
<body>
<xsl:apply-templates select="language | document('kroatiska.xml')/lexicon/language" />
</body>
</html>
</xsl:template>
<xsl:template match="language">
<h3>
<xsl:value-of select="@value"/>
</h3>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="word">
<p>
<xsl:value-of select="."/>
</p>
</xsl:template>
</xsl:stylesheet>
这并不意味着在这种情况下使用xsl:apply-templates
比xsl:for-each
更好。