0

我必须使用 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 标签,但会删除该<div class="iDev">标签。谁能告诉我从给定输入产生所需输出的解决方案。感谢您!

4

1 回答 1

2

我只是要解决您的第一条规则,因为这似乎是您问题的重点。如果您需要有关规则 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>
于 2012-07-31T05:49:56.953 回答