我在转换XML时遇到问题,就像我无法按正确的顺序获取元素。这些元素是随机的,无法预测它们的顺序。
这是我的XML
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<toc>
<layout>
<header>Item 1</header>
<tocItem>item one - a</tocItem>
<tocItem>item one - b</tocItem>
<header>Item 2</header>
<tocItem>item two - a</tocItem>
<tocItem>item two - b</tocItem>
<tocItem>item two - c</tocItem>
<tocItem>item two - d</tocItem>
<tocItem>item two - e</tocItem>
<header>Item 3</header>
<tocItem>item three - a</tocItem>
<header>Item 4</header>
<tocItem>item four - a</tocItem>
<tocItem>item four - b</tocItem>
<tocItem>item four - c</tocItem>
<header>Item 5</header>
<tocItem>item five - a</tocItem>
<tocItem>item five - b</tocItem>
</layout>
<layout>
<header>Item 1</header>
<tocItem>item one - a</tocItem>
<tocItem>item one - b</tocItem>
<header>Item 2</header>
<tocItem>item two - a</tocItem>
</layout>
<layout>
<header>Item 1</header>
<tocItem>item one - a</tocItem>
<tocItem>item one - b</tocItem>
<tocItem>item one - c</tocItem>
<tocItem>item one - d</tocItem>
<tocItem>item one - e</tocItem>
<header>Item 2</header>
<tocItem>item two - c</tocItem>
<tocItem>item two - d</tocItem>
<tocItem>item two - e</tocItem>
<header>Item 4</header>
<tocItem>item four - a</tocItem>
<tocItem>item four - b</tocItem>
<header>Item 5</header>
<tocItem>item five - a</tocItem>
</layout>
</toc>
这里是XSL
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<div class="toc">
<xsl:for-each select="/toc/layout">
<div class="layout">
<xsl:for-each select="/toc/layout/header">
<div class="header">
<p><xsl:value-of select="header" /></p>
</div>
</xsl:for-each>
<xsl:for-each select="/toc/layout/tocItem">
<div class="tocItem">
<p><xsl:value-of select="tocItem" /></p>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
当我尝试上述方法时,它只是重复第一个标头元素和第一个tocItems。在布局div中尝试此代码<xsl:value-of select="." />
时,我得到了所有元素。我的目标是一张一张地取走它们。如下所示。
项目1
第一个-一个
第一项-b
项目2
第二项-
第二项-b
第二项-c
答案 0 :(得分:1)
我没有检查您要达到的目标,但是您的xsl:for-each
显然是错误的。当您编写<xsl:for-each select="/toc/layout">
时,for-each中的context节点是一个<layout>
元素,人们可能希望进一步选择相对于该元素,而不是从文档根目录开始的绝对路径。我不明白为什么您一开始会有两个xsl:for-each
级别。
答案 1 :(得分:1)
通常,如果您只想根据元素名称使用div
属性将所有这些元素转换为HTML class
,则只需一个模板即可:
<xsl:template match="toc | layout | header | tocItem">
<div class="{local-name()}">
<xsl:apply-templates/>
</div>
</xsl:template>
要保持输入顺序,最好简单地apply-templates
或至少最简单。
一个例子是
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="html" indent="no" html-version="5"/>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="toc | layout | header | tocItem">
<div class="{local-name()}">
<xsl:apply-templates/>
</div>
</xsl:template>
</xsl:stylesheet>
使用仅XSLT 3声明<xsl:mode on-no-match="shallow-copy"/>
将身份转换设置为默认处理,但是在早期版本中,您只需将其拼写为
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
请参见https://xsltfiddle.liberty-development.net/ncdD7ne在线进行实验。