【问题标题】:trouble with xml transformationxml转换的麻烦
【发布时间】:2010-08-19 14:14:20
【问题描述】:

我有一个看起来像这样的 xml

<para>
   text text text
   <b>text</b> text text <i>text</i>
</para>

目标是将其转换为 mediaWiki 格式,使用 ''' 表示粗体等。

当我为此编写转换时,模板匹配会忽略 &lt;para&gt; 标记内的所有文本,并且仅转换 &lt;b&gt;s 和 &lt;i&gt;s。我需要帮助。

更新:这是我迄今为止尝试过的:

这是我迄今为止尝试过的。

<xsl:template match="para">
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="b">
<xsl:text>'''</xsl:text><xsl:value-of select="replace(replace(.,'\s+$',''),'^\s+','')" disable-output-escaping="no"/><xsl:text>'''</xsl:text>
</xsl:template>

<xsl:template match="i">
<xsl:text>''</xsl:text><xsl:value-of select="replace(replace(.,'\s+$',''),'^\s+','')" disable-output-escaping="no"/><xsl:text>''</xsl:text>
</xsl:template>

这是我尝试 text() 函数时使用的。

<xsl:template match="text()">
<xsl:value-of select="." disable-output-escaping="no"/>
</xsl:template>

--更新-- 为了不丢失文本块前后的空格以及粗斜体标志,我们还可以检查文本前后的空格。

<xsl:template match="text()">
    <xsl:variable name="originalText" select="."/>
    <xsl:if test="starts-with($originalText,' ')">
        <xsl:text> </xsl:text>
    </xsl:if>
    <xsl:value-of select="normalize-space(.)" disable-output-escaping="no"/>
    <xsl:if test="ends-with($originalText,' ')">
        <xsl:text> </xsl:text>
    </xsl:if>
</xsl:template>

【问题讨论】:

  • 如果您需要帮助,您需要向我们展示您的 XSLT 代码。
  • 与我们分享您已经尝试过的内容?
  • text() 节点将为您提供特定元素内的文本。你试过吗?
  • 这是我迄今为止所尝试的。
  • 请编辑您的问题并将此代码放在那里...并请格式化。谢谢。

标签: xslt text transformation matching


【解决方案1】:

当我为此编写转换时 模板匹配忽略所有 标签内的文本,并且仅 &lt;b&gt;s 和 &lt;i&gt;s 是 转换。我需要帮助。

更新:这是我尝试过的 远:

这是我迄今为止尝试过的。

<xsl:template match="para">  
  <xsl:apply-templates select="*"/>  
</xsl:template>

您的问题正是在此模板中。您的代码忽略除元素之外的任何其他内容 - 子项。 * 的缩写代表child::element()。因此,para 的文本节点子节点根本不会被处理。

解决方案

只需删除上面的模板。然后将选择元素节点的内置 XSLT 模板来处理para 元素。它所做的只是&lt;xsl:apply-templates/&gt;,这是&lt;xsl:apply-templates select="child::node()"/&gt; 的缩写。这将为每个子节点(任何类型,包括文本节点)应用模板。在处理para 的文本节点子节点时,会选择文本节点的内置 XSLT 模板——它所做的只是按原样复制文本。

现在的转变变成了

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="b">
        <xsl:text>'''</xsl:text>
        <xsl:value-of select="replace(replace(.,'\s+$',''),'^\s+','')"/>
        <xsl:text>'''</xsl:text>
    </xsl:template>

    <xsl:template match="i">
        <xsl:text>''</xsl:text>
        <xsl:value-of select="replace(replace(.,'\s+$',''),'^\s+','')" />
        <xsl:text>''</xsl:text>
    </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<para>
   text text text
   <b>text</b> text text <i>text</i>
</para>

结果现在包含 para:

的文本节点子节点
   text text text
   '''text''' text text ''text''

【讨论】:

  • @Dimitre:+1 好的解决方案。但我认为那些fn:replace 会有更好的模式(当然,与问题相同)。也许replace(.,'^\s*(.)\s*$','$1')。或者,如果没有要保留的新行,只需 normalize-space(.)
  • @Alejandro:你可能是对的,我没有深入研究代码——只是解释并解决了主要问题——OP很高兴。
  • @Alejandro:很好的观察。检查&lt;b&gt;&lt;i&gt; 之前/之后的空格以解释&lt;b&gt;text &lt;/b&gt;texttext&lt;i&gt; text&lt;/i&gt; 之类的内容可能也是一个好主意。这与最初的问题无关,但想想还是很有趣的。
  • 这是一个好主意伙计们,我使用了 normalize-space(.) 并检查了匹配文本中前后的空格以及粗体和斜体模板,现在转换更加准确。编辑帖子更新后的代码可能对其他人有用
  • @Prithwin:很高兴您发现这个答案很棒。在 SO 通过接受答案表示感谢和赞赏(只需单击答案左侧的复选标记):)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
相关资源
最近更新 更多