如何使用 XSL 在 XML 转换中查找随机元素
How to find random elements in XML transformation using XSL
我在转换 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>
当我尝试上述方法时,它只是重复第一个 header 元素和第一个 tocItems。在布局 div 中尝试此代码 <xsl:value-of select="." />
时,我获得了所有元素。我的目标是一个一个地获取它们。如下所示。
项目 1
项目一 - a
项目一 - b
项目 2
项目二 -
项目二 - b
项目二 - c
我没有检查你想要达到的目标,但你的 xsl:for-each
显然是错误的。当您编写 <xsl:for-each select="/toc/layout">
时,for-each 中的上下文节点是一个 <layout>
元素,并且人们会期望进一步的选择是相对于该元素的,而不是从根的绝对路径文档。我不明白为什么你首先有两个级别的 xsl:for-each
。
一般来说,如果您只想将所有这些元素转换为 HTML div
,并带有基于元素名称的 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 在线试验。
我在转换 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>
当我尝试上述方法时,它只是重复第一个 header 元素和第一个 tocItems。在布局 div 中尝试此代码 <xsl:value-of select="." />
时,我获得了所有元素。我的目标是一个一个地获取它们。如下所示。
项目 1
项目一 - a
项目一 - b
项目 2
项目二 -
项目二 - b
项目二 - c
我没有检查你想要达到的目标,但你的 xsl:for-each
显然是错误的。当您编写 <xsl:for-each select="/toc/layout">
时,for-each 中的上下文节点是一个 <layout>
元素,并且人们会期望进一步的选择是相对于该元素的,而不是从根的绝对路径文档。我不明白为什么你首先有两个级别的 xsl:for-each
。
一般来说,如果您只想将所有这些元素转换为 HTML div
,并带有基于元素名称的 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 在线试验。