【问题标题】:strange behavior copying nested nodes with xslt使用 xslt 复制嵌套节点的奇怪行为
【发布时间】:2015-10-07 02:03:27
【问题描述】:

我有一个 XML 文档,其中包含一个包含 xhtml 的“body”元素。我正在尝试处理该 html 以删除一些非标准标签。源 xml 文档中没有使用命名空间。

XML 如下所示:

<article>
  <body>
     <p>Paragraph 1</p>
     <p>Paragraph 2</p>
     <p>Paragraph 3 <fig></fig></p>
  </body>
</article>

XSLT 如下所示:

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

<xsl:template match="p">
  <![CDATA[<div>HIT A P</div>]]>
  <xsl:apply-templates mode="copy" select="@*|node()"/>
</xsl:template>
</xsl:stylesheet>

输出是这样的——我不明白为什么它只找到第一个 p 标签:

<div>HIT A P</div>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3 <fig></fig></p>

知道为什么 p 模板只在第一次触发而不是所有 3 段都触发吗??

我也在试图弄清楚为什么添加它不会导致“fig”元素被删除:

<xsl:template match="fig" />

感谢您抽出宝贵时间帮助我。

更新:非常感谢您的回复。我试图过分简化这个问题。我真正在做的是两个 XSLT 进程 - 一个将数据组织成标准格式,第二个 XSLT 进程查看正文中的 HTML 并复制除某些非标准标签之外的所有内容。

我认为我遇到的问题是,在第一个 XSLT 进程之后,正文中的 HTML 是 htmlencoded,而且似乎第二个 XSLT 进程无法转换 HTML。这里有一个更好的例子来说明实际发生的事情:

这是新的 XML(它是早期 xslt 转换的结果 - 因此文本被编码):

<document>
    <article>
        <title>SAMPLE TITLE</title>
        <bodytext>
          &lt;p&gt;Paragraph 1&lt;/p&gt;
          &lt;p&gt;Paragraph 2&lt;/p&gt;
          &lt;p&gt;Paragraph 3&lt;/p&gt;
          &lt;p&gt;
          Paragraph 4 - contains non-standard fig tag
          &lt;fig&gt;
          &lt;graphic href="testgraphic.jpg"/&gt;
          &lt;/fig&gt;
          &lt;/p&gt;
        </bodytext>
    </article>
</document>

这是新的 XSLT:

<xsl:output method="html" encoding="utf-8" indent="yes"/>

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

    <xsl:template match="p">
    <![CDATA[<div>HIT A P</div>]]>
    <xsl:apply-templates mode="copy" select="@*|node()"/>
    </xsl:template>


  <xsl:template match="bodytext">
      <![CDATA[<div>HELLO FROM BODYTEXT</div>]]>
    <xsl:element name="bodytext">
      <xsl:apply-templates />
    </xsl:element>
   </xsl:template>



    <!-- THIS APPEARS TO NEVER GET HIT -->
    <xsl:template match="fig" />


</xsl:stylesheet>

当我运行它时,我得到以下信息:

<document>
    <article>
                <title>SAMPLE TITLE</title>

                &lt;div&gt;HELLO FROM BODYTEXT&lt;/div&gt;<bodytext>

                &lt;p&gt;Paragraph 1&lt;/p&gt;
                &lt;p&gt;Paragraph 2&lt;/p&gt;
                &lt;p&gt;Paragraph 3&lt;/p&gt;
                &lt;p&gt;
                Paragraph 4 - contains non-standard fig tag
                &lt;fig&gt;
                &lt;graphic href="testgraphic.jpg"/&gt;
                &lt;/fig&gt;
                &lt;/p&gt;

                </bodytext>
        </article>
</document>

在此示例中,它无法处理每个段落并删除无花果。但是,如果 XML 不是 htmlencoded,它可以工作。这是工作的 XML:

<document>
    <article>
        <title>SAMPLE TITLE</title>
        <bodytext>
            <p>Paragraph 1</p>
            <p>Paragraph 2</p>
            <p>Paragraph 3 <fig></fig></p>
        </bodytext>
    </article>
</document>

这是输出:

<document>
    <article>
                <title>SAMPLE TITLE</title>

                &lt;div&gt;HELLO FROM BODYTEXT&lt;/div&gt;<bodytext>


        &lt;div&gt;HIT A P&lt;/div&gt;Paragraph 1
     &lt;div&gt;HIT A P&lt;/div&gt;Paragraph 2
     &lt;div&gt;HIT A P&lt;/div&gt;Paragraph 3


                </bodytext>
        </article>
</document>

你知道当传入的数据是 htmlencoded 时我可以如何执行第二个过程吗?再次感谢。

【问题讨论】:

标签: xml xslt


【解决方案1】:

针对您提供的输入 XML 运行您的 XSLT,我没有得到您意外的输出。我得到这个输出,

<article>

   <body>

          &lt;div&gt;HIT A P&lt;/div&gt;
          Paragraph 1

          &lt;div&gt;HIT A P&lt;/div&gt;
          Paragraph 2

          &lt;div&gt;HIT A P&lt;/div&gt;
          Paragraph 3 

   </body>

</article>

这正是您的 XSLT 应该生成的内容。

【讨论】:

  • 正如@michael.hor257k 对您的问题的评论,您不能指望&lt;xsl:template match="fig" /&gt; 匹配转义的XML,它本质上告诉解析器不要将其视为XML 标记——那就是转义 XML 是什么意思。
  • 那么在 PHP 中解决这个问题的唯一方法是引入一个单独的过程来创建一个新的 DOMDocument 并将未转义的内容加载到其中吗?
  • 我刚刚发现 disable-output-escaping="yes" - 这似乎通过保持它不转义来解决问题。谢谢大家的帮助。
  • 而使用 copy-of 而不是 value-of 可能是朝着正确方向迈出的一步。
  • 我会将审查您使用 CDATA 的目的添加到您的待办事项列表中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-08
  • 2015-06-09
  • 1970-01-01
  • 2017-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多