2

我很确定这个问题的答案是否定的,但由于唯一的选择是我认为不优雅的代码,我想我会把它扔掉,看看我是否遗漏了一些东西,同时希望这个问题没有被问到。

鉴于此源 XML:

<root>
    <p>Hello world</p>
    <move elem="content" item="test"/>
    <p>Another text node.</p>
    <content item="test">I can't <b>figure</b> this out.</content>
</root>

我想要这个结果:

<root>
    <block>Hello world</block>
    <newContent>I can't <hmmm>figure</hmmm> this out.</newContent>
    <block>Another text node.</block>
</root>

普通语言描述:

  1. 将 <move .../> 替换为名称与 move 的 @elem 属性匹配且其 @item 与 move 的 @item 属性匹配的元素的处理结果(例如,在这种情况下,元素 [<content>] 的内容被处理为<b> 替换为 <hmm>)。
  2. 防止步骤 1 中的元素以其原始文档顺序写入结果树

问题是输入的 XML 文档会相当复杂和多变。样式表是我正在扩展的第三方转换。为了使用基于模式的解决方案,我必须复制的模板在大小上非常重要,这对我来说似乎很不雅。例如,我知道这会起作用:

<xsl:template match="b">
    <hmmm>
        <xsl:apply-templates/>
    </hmmm>
</xsl:template>
<xsl:template match="p">
    <block>
        <xsl:apply-templates/>
    </block>
</xsl:template>
<xsl:template match="move">
    <xsl:variable name="elem" select="@elem"/>
    <xsl:variable name="item" select="@item"/>
    <xsl:apply-templates select="//*[name()=$elem and @item=$item]" mode="copy-and-process"/>
</xsl:template>
<xsl:template match="content"/>
<xsl:template match="content" mode="copy-and-process">
            <newContent><xsl:apply-templates/></newContent>
</xsl:template>

我想做的是让匹配“内容”的 <xsl:template> 对推送给它的节点敏感。因此,我可以有一个 <xsl:template match="content"/> 仅在从 <root> 而不是 <move> 推送的节点时执行(因此其匹配节点和子节点被抑制)。这样做的好处是,如果更新了第三方样式表的相关模板,我不必担心更新处理 <content> 节点的样式表的副本。我很确定这是不可能的,但我认为值得一问。

4

1 回答 1

1

只需这样做

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kMover" match="move" use="concat(@elem,'+',@item)"/>

 <xsl:key name="kToMove" match="*" use="concat(name(),'+',@item)"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="move">
  <newContent>
      <xsl:apply-templates mode="move" select=
       "key('kToMove', concat(@elem,'+',@item))/node()"/>
  </newContent>
 </xsl:template>

 <xsl:template match="p">
  <block><xsl:apply-templates/></block>
 </xsl:template>

 <xsl:template match="b" mode="move">
  <hmmm><xsl:apply-templates/></hmmm>
 </xsl:template>
 <xsl:template match="*[key('kMover', concat(name(),'+',@item))]"/>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<root>
    <p>Hello world</p>
    <move elem="content" item="test"/>
    <p>Another text node.</p>
    <content item="test">I can't <b>figure</b> this out.</content>
</root>

产生了想要的正确结果:

<root>
   <block>Hello world</block>
   <newContent>I can't <hmmm>figure</hmmm> this out.</newContent>
   <block>Another text node.</block>
</root>
于 2013-05-14T02:16:21.783 回答