XSLT - 遍历元素并转换为 HTML
XSLT - Looping through elements and convert to HTML
我的问题是遍历 XML 文件并找到变量 1 中提到的元素,并使用最简单的方法将它们替换为变量 2 中的元素。
样本XML
下面是示例 XML 文件:
<?xml version="1.0" encoding="utf-8"?>
<root>
<figure id="f0005">
<label>Fig. 1</label>
<caption id="cn0005">
<simple-para id="sp0015">Schematic diagram of the experimental setup.</simple-para>
</caption>
</figure>
<figure id="f0010">
<label>Fig. 2</label>
<caption id="cn0010">
<simple-para id="sp0020">Schematic drawing of the orifice plate.</simple-para>
</caption>
</figure>
</root>
使用这种方法我可以获得输出。但不是所需输出标题中指定的那个。我想我在样式表的 for 循环中做错了什么。请分享您的想法。
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="els_element_name"
select="tokenize('label simple-para figure caption', '\s+')"/>
<xsl:variable name="html_element_name"
select="tokenize('div div div div div', '\s+')"/>
<xsl:template match="/">
<xsl:for-each select="//element()">
<xsl:variable name="ele_name" select="name()"/>
<xsl:if test="index-of($els_element_name, $ele_name)">
<xsl:variable name="array_val">
<xsl:value-of select="index-of($els_element_name, $ele_name)"/>
</xsl:variable>
<xsl:call-template name="optimized_code_start">
<xsl:with-param name="els_element" select="$ele_name"/>
<xsl:with-param name="position" select="$array_val"/>
</xsl:call-template>
<xsl:value-of select="."/>
<xsl:call-template name="optimized_code_end">
<xsl:with-param name="els_element" select="$ele_name"/>
<xsl:with-param name="position" select="$array_val"/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="optimized_code_start">
<xsl:param name="els_element"/>
<xsl:param name="position" as="xs:integer"/>
<xsl:text disable-output-escaping="yes"><</xsl:text>
<xsl:value-of select="$html_element_name[$position]"/>
<xsl:text disable-output-escaping="yes"> class="</xsl:text>
<xsl:value-of select="$els_element"/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
<xsl:for-each select="@*[(name()='id')]">
<xsl:text disable-output-escaping="yes"> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text disable-output-escaping="yes">="</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
</xsl:for-each>
<xsl:for-each select="@*[not(name()='id')]">
<xsl:choose>
<xsl:when test="name() = 'xml:lang'">
<xsl:text disable-output-escaping="yes"> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text disable-output-escaping="yes">="</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text disable-output-escaping="yes"> data-</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text disable-output-escaping="yes">="</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
<xsl:template name="optimized_code_end">
<xsl:param name="els_element"/>
<xsl:param name="position" as="xs:integer"/>
<xsl:text disable-output-escaping="yes"></</xsl:text>
<xsl:value-of select="$html_element_name[$position]"/>
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
</xsl:stylesheet>
需要输出
我想获得如下所述的输出。
<html>
<div class="figure" id="f0005">
<div class="label">Fig. 1</div>
<div class="caption" id="cn0005">
<div class="simple-para" id="sp0015">Schematic diagram of the experimental setup.</div>
</div>
</div>
<div class="figure" id="f0010">
<div class="label">Fig. 2</div>
<div class="caption" id="cn0010">
<div class="simple-para" id="sp0020">Schematic drawing of the orifice plate.
</div>
</div>
</div>
</html>
您可以简单地使用 index-of
和 xsl:element
来匹配输入名称并将其映射到输出名称:
<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="els_element_name"
select="tokenize('label simple-para figure caption', '\s+')"/>
<xsl:variable name="html_element_name"
select="tokenize('div div div div div', '\s+')"/>
<xsl:template match="*[index-of($els_element_name, name()) > 0]">
<xsl:element name="{$html_element_name[index-of($els_element_name, name(current()))]}">
<xsl:apply-templates select="@*"/>
<xsl:attribute name="class" select="name()"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bdxtra/2
另一种可能的方法是创建一个实现映射的样式表,并在 XSLT 3.0 中直接使用 transform
函数 运行 它:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
exclude-result-prefixes="#all"
version="3.0">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:variable name="stylesheet">
<axsl:stylesheet version="3.0">
<axsl:mode on-no-match="shallow-copy"/>
<xsl:for-each select="$els_element_name">
<axsl:template match="{.}">
<axsl:element name="{let $p := position() return $html_element_name[$p]}">
<axsl:apply-templates select="@*"/>
<axsl:attribute name="class" select="'{.}'"/>
<axsl:apply-templates/>
</axsl:element>
</axsl:template>
</xsl:for-each>
</axsl:stylesheet>
</xsl:variable>
<xsl:variable name="els_element_name"
select="tokenize('label simple-para figure caption', '\s+')"/>
<xsl:variable name="html_element_name"
select="tokenize('div div div div div', '\s+')"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:sequence select="$stylesheet"/>
<xsl:sequence
select="transform(
map {
'stylesheet-node' : $stylesheet,
'source-node' : .
}
)?output"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bdxtra/4。对于实际用例,删除或注释掉 <xsl:sequence select="$stylesheet"/>
行,但我保留它以显示创建的样式表。
我的问题是遍历 XML 文件并找到变量 1 中提到的元素,并使用最简单的方法将它们替换为变量 2 中的元素。
样本XML
下面是示例 XML 文件:
<?xml version="1.0" encoding="utf-8"?>
<root>
<figure id="f0005">
<label>Fig. 1</label>
<caption id="cn0005">
<simple-para id="sp0015">Schematic diagram of the experimental setup.</simple-para>
</caption>
</figure>
<figure id="f0010">
<label>Fig. 2</label>
<caption id="cn0010">
<simple-para id="sp0020">Schematic drawing of the orifice plate.</simple-para>
</caption>
</figure>
</root>
使用这种方法我可以获得输出。但不是所需输出标题中指定的那个。我想我在样式表的 for 循环中做错了什么。请分享您的想法。
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="els_element_name"
select="tokenize('label simple-para figure caption', '\s+')"/>
<xsl:variable name="html_element_name"
select="tokenize('div div div div div', '\s+')"/>
<xsl:template match="/">
<xsl:for-each select="//element()">
<xsl:variable name="ele_name" select="name()"/>
<xsl:if test="index-of($els_element_name, $ele_name)">
<xsl:variable name="array_val">
<xsl:value-of select="index-of($els_element_name, $ele_name)"/>
</xsl:variable>
<xsl:call-template name="optimized_code_start">
<xsl:with-param name="els_element" select="$ele_name"/>
<xsl:with-param name="position" select="$array_val"/>
</xsl:call-template>
<xsl:value-of select="."/>
<xsl:call-template name="optimized_code_end">
<xsl:with-param name="els_element" select="$ele_name"/>
<xsl:with-param name="position" select="$array_val"/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="optimized_code_start">
<xsl:param name="els_element"/>
<xsl:param name="position" as="xs:integer"/>
<xsl:text disable-output-escaping="yes"><</xsl:text>
<xsl:value-of select="$html_element_name[$position]"/>
<xsl:text disable-output-escaping="yes"> class="</xsl:text>
<xsl:value-of select="$els_element"/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
<xsl:for-each select="@*[(name()='id')]">
<xsl:text disable-output-escaping="yes"> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text disable-output-escaping="yes">="</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
</xsl:for-each>
<xsl:for-each select="@*[not(name()='id')]">
<xsl:choose>
<xsl:when test="name() = 'xml:lang'">
<xsl:text disable-output-escaping="yes"> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text disable-output-escaping="yes">="</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text disable-output-escaping="yes"> data-</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text disable-output-escaping="yes">="</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
<xsl:template name="optimized_code_end">
<xsl:param name="els_element"/>
<xsl:param name="position" as="xs:integer"/>
<xsl:text disable-output-escaping="yes"></</xsl:text>
<xsl:value-of select="$html_element_name[$position]"/>
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
</xsl:stylesheet>
需要输出
我想获得如下所述的输出。
<html>
<div class="figure" id="f0005">
<div class="label">Fig. 1</div>
<div class="caption" id="cn0005">
<div class="simple-para" id="sp0015">Schematic diagram of the experimental setup.</div>
</div>
</div>
<div class="figure" id="f0010">
<div class="label">Fig. 2</div>
<div class="caption" id="cn0010">
<div class="simple-para" id="sp0020">Schematic drawing of the orifice plate.
</div>
</div>
</div>
</html>
您可以简单地使用 index-of
和 xsl:element
来匹配输入名称并将其映射到输出名称:
<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="els_element_name"
select="tokenize('label simple-para figure caption', '\s+')"/>
<xsl:variable name="html_element_name"
select="tokenize('div div div div div', '\s+')"/>
<xsl:template match="*[index-of($els_element_name, name()) > 0]">
<xsl:element name="{$html_element_name[index-of($els_element_name, name(current()))]}">
<xsl:apply-templates select="@*"/>
<xsl:attribute name="class" select="name()"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bdxtra/2
另一种可能的方法是创建一个实现映射的样式表,并在 XSLT 3.0 中直接使用 transform
函数 运行 它:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
exclude-result-prefixes="#all"
version="3.0">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:variable name="stylesheet">
<axsl:stylesheet version="3.0">
<axsl:mode on-no-match="shallow-copy"/>
<xsl:for-each select="$els_element_name">
<axsl:template match="{.}">
<axsl:element name="{let $p := position() return $html_element_name[$p]}">
<axsl:apply-templates select="@*"/>
<axsl:attribute name="class" select="'{.}'"/>
<axsl:apply-templates/>
</axsl:element>
</axsl:template>
</xsl:for-each>
</axsl:stylesheet>
</xsl:variable>
<xsl:variable name="els_element_name"
select="tokenize('label simple-para figure caption', '\s+')"/>
<xsl:variable name="html_element_name"
select="tokenize('div div div div div', '\s+')"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:sequence select="$stylesheet"/>
<xsl:sequence
select="transform(
map {
'stylesheet-node' : $stylesheet,
'source-node' : .
}
)?output"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bdxtra/4。对于实际用例,删除或注释掉 <xsl:sequence select="$stylesheet"/>
行,但我保留它以显示创建的样式表。