【问题标题】:get data based on values of any attribute根据任何属性的值获取数据
【发布时间】:2012-06-14 09:07:28
【问题描述】:

给定一个节点,例如。

<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="SP" elem8="MC" elem9="DS" elem10="DA" elem11="16"/>

如果任何属性是“DA”,我需要我的输出是“DA”,或者如果任何属性是“BA”,我需要下一个属性的值(即如果 elem7="BA elem8="03" 我想要 "03 " 输出)

没有多重匹配的危险,所以如果一个属性是“BA”,就不会有“DA”属性,但是值可以出现在任何元素中

我已经查看了 attribute:: 标记,但我不确定这是否能满足我的需求。

非常感谢任何帮助

【问题讨论】:

  • 嗯,依赖输入 XML 中的属性顺序通常是不可靠的。见stackoverflow.com/questions/2287861/…。无论如何,我不相信 XSL 检查前置/前处理节点的轴可以应用于属性。
  • 属性名总是elem1、elem2等。有没有办法获取属性名然后替换末尾的数字字符?
  • 要获取节点或属性的名称,请使用name()
  • @Jaloopa 可以使用 substring-after XPATH 方法来完成。看我的回答。

标签: xslt xslt-1.0


【解决方案1】:

我假设您的属性具有 elemN 形式的名称,其中 N = 1,2,3..., 并且它们被相应地排序。

以下 XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="text" />
    <xsl:template match="/SI">
        <xsl:choose>
            <xsl:when test="some $i in @* satisfies $i='DA'">
                <xsl:text>DA</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="attr" select="concat('elem', xs:decimal(substring-after(@*[.='BA']/name(), 'elem')) + 1)" />
                <xsl:value-of select="@*[name() = $attr]" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

应用于以下输入 XML:

<?xml version="1.0" encoding="UTF-8"?>
<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="SP" elem8="MC" elem9="DS" elem10="DA" elem11="16" />

DA 作为输出。

并应用于以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="BA" elem8="03" elem9="DS" elem10="DAs" elem11="16" />

03 作为输出。

编辑

这是 XSLT 1.0 版本(在 Altova XMLSpy 下测试):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="/">
        <xsl:apply-templates select="SI/@*" />
    </xsl:template>

    <xsl:template match="@*">
        <xsl:choose>
        <xsl:when test=". = 'DA'">
            <xsl:text>DA</xsl:text>     
        </xsl:when>
        <xsl:when test=".='BA'">
            <xsl:variable name="attr" select="concat('elem', substring-after(name(), 'elem') + 1)" />
            <xsl:value-of select="/SI/@*[name() = $attr]" />
        </xsl:when>
        <xsl:otherwise/>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 被接受,因为它解决了问题,我发现它比下面@dimitre 的答案更具可读性,但我设法进入了生成 XML 的 C# 代码并设置了一个更容易获得的属性.
  • 这是否依赖于 2.0 版?在 1.0 样式表中尝试变量时,出现以下错误: Expected token ')', found '('. ...(substring-after(@*[.='TM']/name -->(
  • @Jaloopa:正如您在样式表标题中看到的那样,它适用于 XSLT 2.0。您还没有提到您想要 XSLT 1.0 解决方案...
【解决方案2】:

如果任何属性为“DA”,或者值为 如果任何属性为“BA”,则为下一个属性(即,如果 elem7="BA elem8="03" 我想要 "03" 输出)

没有多重匹配的危险,所以如果一个属性是“BA”, 不会有“DA”属性,但值可以出现在任何 元素

这个单一的 XPath 表达式产生想要的值

  string(/*/@*[. = 'DA']
        |
         /*/@*[name()
              =
               concat('elem', substring-after(name(/*/@*[.='BA']), 'elem') +1)]
         )

这是完整的转换:

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

 <xsl:template match="/">
     <xsl:copy-of select=
     "string(/*/@*[. = 'DA']
            |
             /*/@*[name()
                  =
                   concat('elem', substring-after(name(/*/@*[.='BA']), 'elem') +1)]
             )"/>
 </xsl:template>
</xsl:stylesheet>

可以看出,这种转换只是计算 XPath 表达式并将计算结果复制到输出。

在此 XML 文档上应用转换时(您的第二种情况):

<SI elem1="TI"
    elem2="FN"
    elem3="4099450222"
    elem4="TM"
    elem5="4094110000"
    elem6="MT"
    elem7="BA"
    elem8="03"
    elem9="DS"
    elem10="DD"
    elem11="16"/>

结果是

03

当对最初提供的 XML 文档应用相同的转换时(您的第一种情况):

<SI elem1="TI"
    elem2="FN"
    elem3="4099450222"
    elem4="TM"
    elem5="4094110000"
    elem6="MT"
    elem7="SP"
    elem8="MC"
    elem9="DS"
    elem10="DA"
    elem11="16"/>

再次产生所需的正确结果

DA

解释

正确使用 XPath union 运算符 |,以及函数 string()substring-after()name()`concat()

【讨论】:

  • @LukaszBaran:你的也不错。我个人更喜欢避免任何有条件的指令。 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多