【问题标题】:XML to XML with XSLT (Remove, add, alter)使用 XSLT 将 XML 转换为 XML(删除、添加、更改)
【发布时间】:2012-07-28 19:25:24
【问题描述】:

我必须使用 XSLT 从一个 XML (XHTML) 文件转换为另一个。转换规则为:

  1. <div id="ta12" class="bl" style="dis:bl"> 必须替换为 <div class="pass" value="50">
  2. id="t0b" 和 "t1b" 的值必须分别替换为 id="ta0b8" 和 "ta3b8"。
  3. <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 标记,但会删除 &lt;div class="iDev"&gt; 标记。谁能告诉我从给定输入产生所需输出的解决方案。谢谢!

【问题讨论】:

标签: xml xslt xhtml xslt-1.0


【解决方案1】:

我只是要解决您的第一条规则,因为这似乎是您问题的重点。如果您在规则 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>

注意。在之前的解决方案中,我可能给了你这个低效的模板……

清单 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 元素具有类属性的情况下消除对类属性的无关处理。如果你真的想在清单 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 的通用性并想吸取 Attribute Value Templates 的精华,您可以使用清单 5。在清单 5 中,您可以将 'pa' 和 'va' 替换为 Attribute Value Templates , 按要求。该解决方案的另一个缺点是,现在有必要确保@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>

最后,我知道您只对 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>

【讨论】:

  • 实际上,@Rahul,我不是已经在stackoverflow.com/questions/11642627 回答了你的问题吗?
  • 非常感谢您的回复。 :) 是的,您已经回答了问题的第一部分,但在这里我也更改了您建议我这样做的那个问题的输入。根据您的建议,我试图使其更通用(2和3)。我会问他们作为一个单独的问题。再次感谢您的帮助。 :)
  • 请看这里stackoverflow.com/questions/ask 如前所述,我已经发布了规则 2 和 3 的新问题。再次非常感谢。期待您的帮助。
猜你喜欢
  • 2012-07-21
  • 2016-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 2019-04-11
相关资源
最近更新 更多