0

我正在尝试清理我提供的一批 XML。我需要考虑三种情况:

  1. 某些元素中包含纯文本,例如。<item>some text</item>, 它需要被包裹在另一个标签中,例如。<item><p>some text</p></item>
  2. 一些元素已经在其中转义了 XML,例如。<item>&lt;p>some text&lt;/p></item>,需要在不转义的情况下输出:<item><p>some text</p></item>
  3. 一些元素已经转义了需要包装的 XML,例如。<item>some &lt;em>text&lt;/em></item>需要成为<item><p>some <em>text</em></p></item>

<item>在这两种情况下都用作容器。

我可以相对容易地满足条件一,我可以用 满足条件 2 disable-output-escaping,但我不能用这种方法满足条件 3。

<item>如果我可以测试其中的文本是否被转义,我认为我可以满足 2(可能是 3) ,但使用的测试contains(., '&amp;lt;')不匹配。所以...

如何测试节点中的文本是否为转义 XML?

4

1 回答 1

0
  1. 和 3. 两者都需要在 1. 中进行包装和禁用输出转义。不会受到伤害,所以我认为您可以使用相同的模板将它们一起处理。

我没有看到一个明确的检查元素内容是否包含带有纯 XSLT 1.0 手段的转义元素标记,所以我只是尝试了

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/root">
  <html>
    <body>
      <xsl:apply-templates/>
    </body>
  </html>
</xsl:template>

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

<xsl:template match="item[not(*) and not(starts-with(., '&lt;') and substring(., string-length(.)) = '&gt;')]">
  <xsl:copy>
    <p>
      <xsl:value-of select="." disable-output-escaping="yes"/>
    </p>
  </xsl:copy>
</xsl:template>

<xsl:template match="item[not(*)
                          and starts-with(., '&lt;') and substring(., string-length(.)) = '&gt;']">
  <xsl:copy>
    <xsl:value-of select="." disable-output-escaping="yes"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

转换

<root>
<item>some text</item>
<item>&lt;p>some text&lt;/p></item>
<item>some &lt;em>text&lt;/em></item>
</root>

进入

<html><body>
<item><p>some text</p></item>
<item><p>some text</p></item>
<item><p>some <em>text</em></p></item>
</body></html>

显然它也会<item>&lt;...></item>变成<item><...></item>. 您可以尝试实现更多的字符串检查,但如果没有针对转义的 XML 片段的完整解析器,则始终可以在字符串检查失败的地方构造输入样本。

于 2013-07-10T12:18:28.217 回答