【问题标题】:XML Key/value manipulation on condition using XSLT使用 XSLT 在条件下进行 XML 键/值操作
【发布时间】:2013-06-24 14:51:38
【问题描述】:

我有这样的数据 -

<item>
    <name>Bob</name>
    <fav_food>pizza</fav_food>
    <key>Salary</key>
    <value />
    <value2>1000</value2>
    <value3 />
</item>

我希望我的输出看起来像这样 -

<item>
    <name>Bob</name>
    <fav_food>pizza</fav_food>
    <Salary>1000</Salary>
</item>

在这种情况下,Salary 的值为 1000,因为 value 为空而 value2 不是(value 的优先级高于 value2,而 value2 的优先级高于 value3)。

保证 value、value2 和 value3 都存在,并且其中只有一个是非空的。是否可以使用 XSLT 转换来执行此操作?

目前,这是我的变换。

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

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

<xsl:template match="key">
    <xsl:element name="{substring-before(substring-after(.,'{'),'}')}"> 
        <xsl:choose>
            <xsl:when test="value != ''">
                <xsl:value-of select="following-sibling::value" />
            </xsl:when>
            <xsl:when test="value2 != ''">
                <xsl:value-of select="following-sibling::value2" />
            </xsl:when>
            <xsl:when test="value3 != ''">
                <xsl:value-of select="following-sibling::value3" />
            </xsl:when>
        </xsl:choose>
   </xsl:element> 
</xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 每个&lt;item&gt; 可以有多个&lt;key&gt;s 吗?知道这一点很重要。我猜不是,根据您的代码。此外,您的代码是否正常工作,而您只是想要一个更好的方法来做到这一点?还是你的代码有问题?如果是,请显示实际输出。
  • 我保证每件商品只有一把钥匙。我的代码不起作用,基本上无论我的值是什么,我的所有键都会得到一个空字符串。
  • 空字符串在哪里?请显示你得到的输出。另外,当您的输入中没有{ 时,为什么还要有substring-after() 等?或者,如果您显示的输入以这种方式不现实,请显示现实的输入。
  • substring-after() 是因为我的密钥格式类似于 &lt;key&gt;{Salary}&lt;/key&gt;,我不得不取出 {}。但是,Mark 发布的解决方案有效(当我添加 substring-after() 时)。

标签: xml xslt xml-parsing xslt-1.0 xslt-2.0


【解决方案1】:

我认为你可以简单地做

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

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

<xsl:template match="key">
  <xsl:element name="{.}">
    <xsl:copy-of select="../(value, value2, value3)/text()"/>
  </xsl:element>
</xsl:template>

<xsl:template match="item/value | item/value2 | item/value3"/>

</xsl:stylesheet>

您可能想要或需要调整元素名称生成,但我没有应用您的 name="{substring-before(substring-after(.,'{'),'}')}",因为我在您的输入示例中看不到任何大括号。

【讨论】:

  • 我本来打算建议xsl:value-of select="../(value, value2, value3)" separator="",但这是同一个想法。但考虑到“优先事项”的说法,我强烈怀疑我们还没有看到完整的规范。
猜你喜欢
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多