【问题标题】:Why does an element appear twice after transformation?为什么一个元素在变换后会出现两次?
【发布时间】:2010-08-05 13:33:56
【问题描述】:

我正在使用 Perl 和 XSL。我尝试将 <Interval> 的值更改为 XML 文件中的某个数字。我的 XML 如下所示:

<?xml version="1.0"?>
<Config>
    <Enabled>false</Enabled>
    <Interval>5</Interval>
</Config>

我的 XSL 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="node()|@*">
    <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>
    <xsl:template match="/Config/Interval">
<xsl:element name="PollingInterval">
    <xsl:element name="Interval">77</xsl:element>
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

问题是我的输出有两次元素&lt;Interval&gt;

<?xml version="1.0"?>
<Config>
    <Enabled>false</Enabled>
    <Interval><Interval>77</Interval></Interval>
</Config>

请帮忙。

【问题讨论】:

  • 好问题 (+1)。有关问题的解释和完整而简单的解决方案,请参阅我的答案。

标签: xml perl xslt


【解决方案1】:

问题是我的输出有 元素两次:

<?xml version="1.0"?> 
<Config> 
    <Enabled>false</Enabled> 
    <Interval><Interval>77</Interval></Interval>

</Config>

不是真的!

在提供的 XML 文档上应用此转换时的输出是:

<Config>
    <Enabled>false</Enabled>
    <PollingInterval><Interval>77</Interval></PollingInterval>
</Config>

如果您想删除任一元素,只需删除相应的 &lt;xsl:element&gt; 指令即可。

例如:去掉&lt;xsl:element name="PollingInterval"&gt;的变换变成:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/Config/Interval">
      <xsl:element name="Interval">77</xsl:element>
    </xsl:template>
</xsl:stylesheet>

在提供的 XML 文档上应用它的结果是

<Config>
    <Enabled>false</Enabled>
    <Interval>77</Interval>
</Config>

我建议进一步简化转换并匹配Interval 的文本节点子节点。这可能是最短和最简单的解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

    <xsl:template match="Interval/text()">
      <xsl:text>77</xsl:text>
    </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<Config>
    <Enabled>false</Enabled>
    <Interval>5</Interval>
</Config>

产生想要的结果

<Config>
    <Enabled>false</Enabled>
    <Interval>77</Interval>
</Config>

如果您有许多 Interval 元素,并且只想将值 5 替换为 77,那么除了身份规则之外的唯一模板应该是:

<xsl:template match="Interval/text()[.=5]">
  <xsl:text>77</xsl:text>
</xsl:template>

【讨论】:

    【解决方案2】:

    这个样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="Interval/text()">77</xsl:template>
    </xsl:stylesheet>
    

    输出:

    <Config>
        <Enabled>false</Enabled>
        <Interval>77</Interval>
    </Config>
    

    注意:如果您发布其他输入样本并描述绑定,我们可以向您展示如何提取新数字。

    编辑:更短。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多