1

我正在尝试使用 XSLT 从一个 XML (XHTML) 文件转换为另一个。我必须添加一些新元素和属性,删除一些元素和属性以及更新一些现有属性的值。因此,借助本论坛中提供的宝贵帮助,我能够按照我之前的问题的答案完成许多任务:XML to XML with XSLT- Add, Remove, Modify Elements and Attributes但是当元素具有相同的名称和相同的属性时,就会出现问题。那时我无法区分它以进行修改。例如:我在 id="123" 的 div 标签后面有两个 type="t/j" 的脚本,在 head 标签内有一个 type="t/j" 的脚本。我必须删除 src="abc.js" 的脚本元素,仅当它出现在 div 标记之后(不在 head 标记内)并将 xyz.js 的值更改为 lmn.js。我已在我的源文件和所需文件中就这些修正案发表了评论。为了消除 onClick 事件,我传递了一个模板匹配,它使用 @onClick 什么都不做,它根据要求从任何地方删除 onClick 事件。但是,当我应用相同的技术来删除“跨度”时 来自特定位置的标签(在源文件中注释)然后它不仅从那里删除,而且从所有其他我不想的地方删除。请在下面找到我的 XML 文件 -

源文件:

<?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" />
<script type="t/j" src="abc.js"></script>
</head>

<body>
<div id="o">
<div id="m">
<div id="nD">
<p id="nT">
Part 1</p>
</div>

<div class="TF" id="123">
<!--CHANGE THE VALUE OF XYZ.JS TO LMN.JS-->
<script type="t/j" src="xyz.js"></script>
<!--REMOVE THIS SCRIPT-->
<script type="t/j" src="abc.js"></script>
<div class="iD">
<img alt="" src="ic.gif" />
<span class="iDe">ABC</span><br/>
<div class="iDev">
<div id="ta12" class="bl" style="dis:bl"></div>

<div class="q">
<br/><br/>
<!--TO REMOVE SPAN TAG FROM HERE-->
<div id="ta12" class="bl" style="dis:bl">1<span style="color: #000000;"> XYZ</span> </div>
<!--REMOVE ONCLICK EVENT -->
<br/>T <input type="radio" name="op12" id="t12" onclick="getFeedback()"/> 
F <input type="radio" name="op12" id="f12" onclick="getFeedback()"/>
<div>C </div>
<div>In </div>

<div>
<div></div>
</div>
</div>

</div>
</div>
</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" />
<script type="t/j" src="abc.js"></script>
</head>

<script type="t/j" src="pqr.js"></script>
<script type="t/j" src="stu.js"></script>

<body onload="load()" onunload="unload()">
<div id="o">
<div id="m">
<div id="nD">
<p id="nT">
Part 1</p></div>

<div class="QT" id="456">
<script type="t/j" src="lmn.js"></script>
<form name="form1" id="q8" action="js:cal();">
<div class="iD">
<img alt="" src="ic.gif" />
<span class="iDe">ABC</span>
<div class="iDev">
<!--ADD THIS DIV TAG-->
<div class="pa" value="10"></div>

<div class="q">
<div id="ta8" class="bl" style="dis:bl">XYZ 
</div><br/>
<input type="radio" name="ke8" value="0" />
<div id="tab8" class="bl" style="dis:bl">T 
</div>
<input type="radio" name="ke8" value="1" />
<div id="tab8" class="bl" style="dis:bl">F 
</div>
</div>
<br/><input type="submit" name="sub" value="Done"/>
</div></div>
</form>
</div>
</div>
</div>

</body></html>

我正在使用 XSLT 1.0。因此,根据建议和一些修改(尽管在 id="1" 等某些地方有所不同),我的 XSLT 看起来像: 已更新

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xhtml="http://www.w3.org/1999/xhtml"
 xmlns="http://www.w3.org/1999/xhtml"
 exclude-result-prefixes="xhtml">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*" />

<xsl:template match="@*|node()">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="xhtml:body">
<script type="t/j" src="pqr.js"></script>
<script type="t/j" src="stu.js"></script>
<body onload="loadPage()" onunload="unloadPage()">
  <xsl:apply-templates select="@*|node()"/>
</body>
</xsl:template>
<xsl:template match="xhtml:div[@id='123']/@class">
  <xsl:attribute name="class">QT</xsl:attribute>
   <xsl:attribute name="id">456</xsl:attribute> 
</xsl:template>
<xsl:template match="xhtml:script[@src='xyz.js']">
 <xsl:copy>
  <xsl:apply-templates select="@*[not(@src)]" />
  <xsl:attribute name="src">lmn.js</xsl:attribute>
  <xsl:apply-templates select="node()" />
 </xsl:copy>
</xsl:template>
<xsl:template match="xhtml:body//xhtml:script[@src='abc.js']" />

<xsl:template match="xhtml:div[@class='iD']">
  <form name="form">
   <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
   <xsl:apply-templates select="following-sibling::xhtml:div[1]" mode="inside-form"/>
   <br/><input type="submit" name="sub" value="Done"/> 
  </form>
</xsl:template>
<xsl:template match="xhtml:div[@id='ta12']">
  <xsl:attribute name="class">pa</xsl:attribute>
  <xsl:attribute name="value">10</xsl:attribute>
</xsl:template>

<xsl:template match="xhtml:div[@class='iDev']">
   <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
     <div id="ta8" class="bl" style="dis:bl">XYZ</div>
<br/>
   <input type="radio" name="ke8" value="0" />
<div id="tab8" class="bl" style="dis:bl">T</div>
   <input type="radio" name="ke8" value="1" />
<div id="tab8" class="bl" style="dis:bl">F</div>
</xsl:template>

</xsl:stylesheet>

我得到的输出——

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html;  charset=utf-8"/>
<script type="t/j" src="abc.js" xml:space="preserve"/>
</head>
<script type="t/j" src="pqr.js"/>
<script type="t/j" src="stu.js"/>
<body onload="loadPage()" onunload="unloadPage()">
<div id="o">
<div id="m">
<div id="nD">
<p id="nT">
Part 1</p>
</div>
<!--VALUE OF CLASS HAS CHANGED BUT NOT ID-->
<div class="QT" id="123">
<script type="t/j" src="lmn.js" xml:space="preserve"/>
<form name="form">
<div class="iD">
<img alt="" src="ic.gif"/>
<span class="iDe">ABC</span>
<br clear="none"/>
<!--DIV TAG WITH CLASS=IDEV IS MISSING-->
<div class="pa" value="10">
<div class="q">
<!--BR HAVE APPEARED WITH ATTRIBUTE CLEAR-->
<br clear="none"/>
<br clear="none"/>
<!--INPUT TAGS HAVE APPEARED TWICE-->
<br clear="none"/>T <input type="radio" name="op12" id="t12" onclick="getFeedback()"/> 
F <input type="radio" name="op12" id="f12" onclick="getFeedback()"/>
<div>C </div>
<div>In </div>
<div>
<div/>
</div>
</div>
</div>
<div id="ta8" class="bl" style="dis:bl">XYZ</div>
<br/>
<input type="radio" name="ke8" value="0"/>
<div id="tab8" class="bl" style="dis:bl">T</div>
<input type="radio" name="ke8" value="1"/>
<div id="tab8" class="bl" style="dis:bl">F</div>
</div>
<br/>
<input type="submit" name="sub" value="Done"/>
</form>
</div>
</div>
</div>
</body>
</html>

感谢您!

4

1 回答 1

1

在 90% 的 XSLT 问题中,最大的挑战不是问题的技术方面,而是如何以匹配模式和相应输出的形式表达转换规则。我不会给你一个样式表,而是给你一个问题的模式和输出视图。您应该能够从中制作样式表。不涉及特殊技术。

比较您的输入和输出文档,我将描述转换规则如下。

  1. 将输入文档复制到输出,但以下情况除外。
  2. 在 <body> 之前加上以下文字

    <script type="t/j" src="pqr.js" />
    <script type="t/j" src="pqr.js" />
    
  3. 附加到 <body> 元素属性 @onload="load()" 和 @onunload="unload()"。

  4. 对于任何具有@id=123 的<div> 元素,将@class 更改为QT,将id 更改为456。
  5. 对于任何 <script> 元素,将 @src="xyz.js" 更改为 "lmn.js"。
  6. 对于正文中带有@src="abc.js"的任何 <script> 元素,删除。
  7. 将任何具有 @class="iD" 的 <div> 元素包装在 <form> 中并且在表单关闭之前,包括以下文字

    <br/><input type="submit" name="sub" value="Done"/>
    
  8. 用 @id="ta12" 替换任何 <div> 元素:

    <div id="pa" value="10" />
    
  9. 复制任何 <div class="iDev">,但将其子项替换为以下文字

    <div id="ta8" class="bl" style="dis:bl">XYZ</div>
    <br/>
    <input type="radio" name="ke8" value="0" />
    <div id="tab8" class="bl" style="dis:bl">T</div>
    <input type="radio" name="ke8" value="1" />
    <div id="tab8" class="bl" style="dis:bl">F</div>
    

更新

OP 要求提供第 5 点的模板。所以就在这里。这是关于如何复制节点的通用解决方案,只需更改一个属性...

<xsl:template match="xhtml:script[@src='xyz.js']">
 <xsl:copy>
  <xsl:apply-templates select="@*[not(@src)]" />
  <xsl:attribute name="src">lmn.js</xsl:attribute>
  <xsl:apply-templates select="node()" />
 </xsl:copy>
</xsl:template>

如果您不介意使用不太通用的解决方案并且可以假设脚本元素没有子元素并且只有一个其他属性 @type="t/j" ,例如,您可以使用更简洁和特定的模板像这样(但我不推荐它 - 我只是在列出你的选择......

<xsl:template match="xhtml:script[@src='xyz.js']">
 <xhtml:script type="t/j" src="lmn.js" />
</xsl:template>

对于第 6 点,它是...

<xsl:template match="xhtml:body//xhtml:script[@src='abc.js']" />
于 2012-07-23T06:00:19.577 回答