我必须使用XSLT从一个XML(XHTML)文件转换到另一个文件。转换的规则是:
<div id="ta12" class="bl" style="dis:bl">
必须替换为<div class="pass" value="50">
- id="t0b"one_answers"t1b"的值必须分别替换为id="ta0b8"one_answers"ta3b8"
<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">
标记。有人能告诉我从给定的输入中产生所需输出的解决方案吗。谢谢你!
我将讨论您的第一条规则,因为这似乎是您问题的焦点。如果您需要有关规则2和3的帮助,请分别提出问题。
通常,XSLT1.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:apply-templates替换xsl:copy-of。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>
注:。在以前的解决方案中,我可能给了你这个低效的模板。。。
清单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,因为当焦点项是属性时,attribute::axis总是返回空序列。清单3背后的想法是,在匹配的输入div元素具有class属性的情况下,消除对class属性的无关处理。如果您真的想在XSLT1.0中获得比清单2更高的效率,您可以按照清单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的通用性,并想吸取AttributeValueTemplates的精华,那么可以使用清单5。在清单5中,您可以根据需要将"pa"one_answers"va"替换为"属性值模板"。该解决方案的另一个缺点是,现在必须确保@class和@value属性不在子xsl:apply-templates中处理,否则它们将重写预期的文字值,而不仅仅是一种效率度量。
清单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>
最后,我知道您只对XSLT1.0感兴趣,但为了好玩,我将介绍XSLT2.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>