代码之家  ›  专栏  ›  技术社区  ›  RahulD

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

  •  1
  • RahulD  · 技术社区  · 12 年前

    我正在尝试使用XSLT将一个XML(XHTML)文件转换为另一个。我必须添加一些新的元素和属性,删除一些元素和属性以及更新一些现有属性的值。因此,在这个论坛上提供的宝贵帮助下,我能够按照我之前问题的答案完成许多任务: XML to XML with XSLT- Add, Remove, Modify Elements and Attributes 但是当元素具有相同的名称和一个相同的属性时,问题就出现了。在这一点上,我无法区分它进行修改。 例如:在div标记id=“123”后有两个type=“t/j”的脚本,在head标记内有一个type=”t/j“的脚本。我必须删除src=“abc.js”的script元素,只有当它出现在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>
    

    我使用的是XSLT1.0。因此,对于as per建议和一些修改(尽管在某些地方有所不同,如where 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 回复  |  直到 12 年前
        1
  •  1
  •   Sean B. Durkin    12 年前

    在90%的XSLT问题中,最大的挑战不是问题的技术方面,而是如何以匹配模式和相应输出的形式阐明转换规则。与其给你一张样式表,我还不如给你一个图案&问题的输出视图。你应该能够根据这个制作一个样式表。不涉及特殊技术。

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

    1. 将输入文档复制到输出,但以下情况除外。
    2. 在<身体>具有以下文字

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

    4. 对于任何<div>将@class更改为QT并将id更改为456。
    5. 对于任何<脚本>元素将@src=“xyz.js”更改为“lmn.js”。
    6. 对于任何<脚本>元素 在体内 使用@src=“abc.js”,删除。
    7. 将任何<div>在<形式>在表格结束之前,包括以下文字

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

      <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>
    

    如果你不介意有一个不太通用的解决方案,并且可以假设script元素没有子元素,只有一个其他属性@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']" />