9

我有这个 XML:

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

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

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

我已经看到了有关 Becker 方法的一些信息,但我无法真正遵循它。XPath 真的不是我的强项。

4

4 回答 4

22

I. 在 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

二、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 长度有限。

另一方面,如果$cond是,true()那么上面的第一个参数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 表达式中替换这些字符串,您不必担心指定任何长度。

于 2012-10-19T15:34:13.533 回答
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")))
于 2012-10-19T15:39:11.503 回答
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"]))
)
于 2015-11-11T22:54:25.380 回答
0

试试这个

if (condition) 
then 
  if (condition) stmnt 
  else stmnt 
else 
  if (condition) stmnt 
  else stmnt 
于 2012-10-19T15:30:53.643 回答