使用XSLT进行XML到XML的转换(添加,删除,修改)

时间:2012-07-23 04:43:42

标签: xslt xhtml xslt-1.0

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

感谢你!

1 个答案:

答案 0 :(得分:1)

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

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

  1. 将输入文档复制到输出中,但以下情况除外。
  2. 在&lt; body&gt;之前使用以下文字

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

  4. 对于任何&lt; div&gt; @ id = 123的元素,将@class更改为QT,将id更改为456。
  5. 对于任何&lt;脚本&gt;元素将@ src =“xyz.js”更改为“lmn.js”。
  6. 对于任何&lt;脚本&gt; @ src =“abc.js”中的元素 ,删除。
  7. 包装任何&lt; div&gt;在&lt; form&gt;中具有@ class =“iD”的元素在表单关闭之前,包括以下文字

    <br/><input type="submit" name="sub" value="Done"/>
    
  8. 替换任何&lt; div&gt;带有@ id =“ta12”的元素替换:

    <div id="pa" value="10" />
    
  9. 复制任何&lt; div class =“iDev”&gt;,除了用以下文字替换其子项

    <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>
    
  10. 更新

    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']" />