xpath中嵌套的条件if else语句

时间:2012-10-19 15:15:02

标签: xpath conditional if-statement xpath-2.0

我有这个XML:

<property id="1011">
    <leasehold>No</leasehold>
    <freehold>Yes</freehold>
    <propertyTypes>
        <propertyType>RESIDENTIAL</propertyType>
    </propertyTypes>
</property>

我想创建一个xpath语句,它与下面嵌套的if-else伪代码块相同。

if( propertyTypes/propertyType == 'RESIDENTIAL') {
    if( leasehold == 'Yes' ){
        return 'Rent'
    } else
        return 'Buy'
    }
} else {
    if( leasehold == 'Yes' ){
        return 'Leasehold'
    } else
        return 'Freehold'
    }
}

我见过Becker的方法但我无法真正遵循它。 XPath真的不是我的强项。

4 个答案:

答案 0 :(得分:21)

<强>予。在XPath 2.0中,只需将其转换为:

   if(/*/propertyTypes/propertyType = 'RESIDENTIAL')
    then
     (if(/*/leasehold='Yes')
       then 'Rent'
       else 'Buy'
     )
     else
       if(/*/leasehold='Yes')
         then 'Leasehold'
         else 'Freehold'

基于XSLT 2.0的验证

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:sequence select=
   "if(/*/propertyTypes/propertyType = 'RESIDENTIAL')
   then
     (if(/*/leasehold='Yes')
       then 'Rent'
       else 'Buy'
     )
     else
       if(/*/leasehold='Yes')
         then 'Leasehold'
         else 'Freehold'
   "/>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<property id="1011">
    <leasehold>No</leasehold>
    <freehold>Yes</freehold>
    <propertyTypes>
        <propertyType>RESIDENTIAL</propertyType>
    </propertyTypes>
</property>

评估XPath表达式并将此评估结果复制到输出中:

Buy

<强> II。 XPath 1.0解决方案

在XPath 1.0中,没有if运算符。

条件语句仍然可以使用单个XPath 1.0表达式实现,但这更棘手,表达式可能不太容易阅读和理解。

这是一种通用方式(由Jeni Tennison首先提出),当条件$stringA$cond并生成true()时生成$stringB

concat(substring($stringA, 1 div $cond), substring($stringB, 1 div not($cond)))

此公式的主要成就之一是它适用于任何长度的字符串,不需要指定长度

<强>解释

这里我们使用的事实是:

number(true()) = 1

number(false()) = 0

那个

1 div 0 = Infinity

因此,如果$condfalse,则concat()的第一个参数为:

 substring($stringA, Infinity)

这是空字符串,因为$stringA的长度有限。

另一方面,如果$condtrue(),则上面concat()的第一个参数为:

sibstring($stringA, 1) 

只是$stringA

因此,根据$cond的值,上面concat()的两个参数中只有一个是非空字符串(分别为$stringA$stringB)。

将此通用公式应用于特定问题,我们可以将大条件表达式的前半部分转换为:

concat(
           substring('rent',
                      1 div boolean(/*[leasehold='Yes'
                                     and
                                       propertyTypes/propertyType = 'RESIDENTIAL'
                                      ]
                                  )
                      ),
           substring('buy',
                      1 div not(/*[leasehold='Yes'
                                     and
                                       propertyTypes/propertyType = 'RESIDENTIAL'
                                      ]
                                  )
                      )
               )

这可以让您了解如何将整个条件表达式转换为单个XPath 1.0表达式。

基于XSLT 1.0的验证

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

 <xsl:template match="/">
  <xsl:copy-of select=
   "concat(
           substring('rent',
                      1 div boolean(/*[leasehold='Yes'
                                     and
                                       propertyTypes/propertyType = 'RESIDENTIAL'
                                      ]
                                  )
                      ),
           substring('buy',
                      1 div not(/*[leasehold='Yes'
                                     and
                                       propertyTypes/propertyType = 'RESIDENTIAL'
                                      ]
                                  )
                      )
               )
   "/>
 </xsl:template>
</xsl:stylesheet>

当在提供的XML文档(上面)上应用此转换时,将评估XPath表达式并将此评估的结果复制到输出:

buy

请注意

如果您决定使用长度与原始字符串不同的其他字符串替换特定字符串,则只需在上面的XPath 1.0表达式中替换这些字符串,您就不必担心指定任何长度。

答案 1 :(得分:2)

Becker的数据处理方法如下:

concat(substring('Rent',      1 div boolean(propertyTypes/propertyType ="RESIDENTIAL" and leasehold="Yes")),
       substring('Buy',       1 div boolean(propertyTypes/propertyType ="RESIDENTIAL" and leasehold="No")),
       substring('Leasehold', 1 div boolean(propertyTypes/propertyType!="RESIDENTIAL" and leasehold="Yes")),
       substring('Freehold',  1 div boolean(propertyTypes/propertyType!="RESIDENTIAL" and leasehold="No")))

答案 2 :(得分:1)

今天花了一整天,但对我来说这适用于Xpath 1.0:

concat(
substring(properties/property[@name="Headline"], 1, string-length(properties/property[@name="Headline"]) * 1), 
substring(properties/property[@name="Name"], 1, not(number(string-length(properties/property[@name="Headline"]))) * string-length(properties/property[@name="Name"]))
)

答案 3 :(得分:0)

试试这个

if (condition) 
then 
  if (condition) stmnt 
  else stmnt 
else 
  if (condition) stmnt 
  else stmnt