我必须使用XSLT从一个XML(XHTML)文件转换为另一个。转型规则是:
<div id="ta12" class="bl" style="dis:bl">
必须替换为<div class="pass" value="50">
<input type="radio" name="o0" id="t0"/>
必须替换为<input type="radio" name="key0b8" value="0" id="ta0q" class="block" />
(同样在文件中)输入文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="iDev">
<div id="ta12" class="bl" style="dis:bl"></div>
<div class="q">
<div id="t0b" class="block">1<span style="color">TEXT1</span>
</div><br />
T <input type="radio" name="o0" id="t0"/>
F <input type="radio" name="op0" id="f0"/>
<div id="sfb"></div>
</div><br />
<div class="q">
<div id="t1b" class="block">2<span style="color">TEXT2</span>
</div><br />
T <input type="radio" name="o1" id="t1" />
F <input type="radio" name="op1" id="f1" />
<div id="sfb"></div>
</div>
</div>
</body>
</html>
输出文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="iDev">
<div class="pass" value="50"></div>
<div class="q">
<div id="ta0b8" class="block">1<span style="color">TEXT1</span>
</div><br />
T<input type="radio" name="key0b8" value="0" id="ta0q" />
F<input type="radio" name="key0b8" value="1" id="ta1q" />
<div id="sfb"></div>
</div><br />
<div class="q">
<div id="ta3b8" class="block">2 <span style="color">TEXT2</span>
</div><br />
T<input type="radio" name="key3b8" value="0" id="ta0q3" />
F<input type="radio" name="key3b8" value="1" id="ta1q3" />
<div id="sfb"></div>
</div>
</div>
</body>
</html>
在我的XSLT中,我创建了一个包含整个输入文件的身份模板,然后我尝试进行必要的修改。我能够通过 -
完成第一项任务<xsl:template match="xhtml:div[@id='ta12']">
<xsl:attribute name="class">pa</xsl:attribute>
<xsl:attribute name="value">10</xsl:attribute>
</xsl:template>
在输出中,它会生成所需的Div标记,但会删除<div class="iDev">
标记。谁能告诉我从给定输入产生所需输出的解决方案。谢谢你!
答案 0 :(得分:2)
我只是要解决你的第一条规则,因为这似乎是你问题的焦点。如果您需要有关规则2和规则3的帮助,请提出单独的问题。
通常,XSLT 1.0复制元素(非深层)的解决方案模式如下所示。非深度,我的意思是删除任何子节点。
清单1
<xsl:template match="some-element-pattern">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:attribute name="my-attrib-to-set">value-to-set</xsl:attribute>
</xsl:copy>
</xsl:template>
或者,您可以将xsl:copy-of替换为xsl:apply-templates,如果有其他属性处理的可能性,则直接复制。 xsl:apply-templates是更通用的形式。
因此,将此解决方案模式应用于您的案例,您想要的模板是......
清单2
<xsl:template match="xhtml:div[@id='ta12']">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:attribute name="class">pa</xsl:attribute>
<xsl:attribute name="value">10</xsl:attribute>
</xsl:copy>
</xsl:template>
NB。在以前的解决方案中,我可能已经给你这个效率低下的模板......
清单3
<xsl:template match="xhtml:div[@id='ta12']">
<xsl:copy>
<xsl:apply-templates select="@*[not(@class)]" />
<xsl:attribute name="class">pa</xsl:attribute>
</xsl:copy>
</xsl:template>
我现在意识到这是错误的。谓词not(@class)是无意义的并且总是返回true,因为当焦点项是属性时,属性:: axis总是返回一个空序列。列表3背后的思想是在匹配的输入div元素具有class属性的情况下消除class属性的无关处理。如果你真的想在清单2中获得这种效率,那么在XSLT 1.0中,你可以像清单4一样,但是代码有点丑陋,而且我不确定它是否值得。
清单4
<xsl:template match="xhtml:div[@id='ta12']">
<xsl:copy>
<xsl:apply-templates select="@*[local-name()!='class']
[local-name()!='value']" />
<xsl:attribute name="class">pa</xsl:attribute>
<xsl:attribute name="value">10</xsl:attribute>
</xsl:copy>
</xsl:template>
清单4仅适用于null名称空间中的类和值。如果有问题的属性位于命名空间中,则需要进行一些更改。
这是最后的选择。如果你准备牺牲xsl:copy的通用性并希望吮吸属性值模板的多汁骨髓,你可以使用清单5.在清单5中,你可以用属性值模板替换'pa'和'va' , 按要求。此解决方案的另一个缺点是,现在必须(而不仅仅是效率度量)确保在子xsl:apply-templates中不处理@class和@value属性,否则它们将覆盖预期的文字值。
清单5
<xsl:template match="xhtml:div[@id='ta12']">
<xhtml:div class="pa" value="va">
<xsl:apply-templates select="@*[local-name()!='class']
[local-name()!='value']" />
</xhtml:div>
</xsl:template>
最后,我知道你只对XSLT 1.0感兴趣,但为了一点乐趣,我将提到XSLT 2.0解决方案的一般模式。这在清单6中显示。
清单6
<xsl:template match="some-element-pattern">
<xsl:copy>
<xsl:apply-templates select="@* except @my-attrib-to-set" />
<xsl:attribute name="my-attrib-to-set">value-to-set</xsl:attribute>
</xsl:copy>
</xsl:template>