XPath to return default value if node not present

后端 未结 5 1888
无人及你
无人及你 2020-12-05 05:53

Say I have a pair of XML documents


    
    mystring

and



        
相关标签:
5条回答
  • 2020-12-05 05:55
    /Foo/(Baz/string(), 'not-found')[1]
    
    0 讨论(0)
  • 2020-12-05 06:05

    @Alejandro provided the best XPath 1.0 answer, which has been known for years, since first used by Jeni Tennison almost ten years ago.

    The only problem with this expression is its shiny elegance, which makes it difficult to understand by not only novice programmers.

    In a hosted XPath 1.0 (and every XPath is hosted!) one can use more understandable expressions:

    string((/Foo/Baz | $vDefaults[not(/Foo/Baz/text())]/Foo/Baz)[last())
    

    Here the variable $vDefaults is a separate document that has the same structure as the primary XML document, and whose text nodes contain default values.

    Or, if XSLT is the hosting language, one can use the document() function:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my">
     <xsl:output  method="text"/>
    
     <my:defaults>
        <Foo>
            <Bar/>
            <Baz>not-found</Baz>
      </Foo>
     </my:defaults>
    
     <xsl:template match="/">
         <xsl:value-of select=
         "concat(/Foo/Baz,
               document('')[not(current()/Foo/Baz/text())]
                                            /*/my:defaults/Foo/Baz
               )"/>
     </xsl:template>
    </xsl:stylesheet>
    

    Or, not using concat():

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my">
     <xsl:output  method="text"/>
    
     <my:defaults>
        <Foo>
            <Bar/>
            <Baz>not-found</Baz>
      </Foo>
     </my:defaults>
    
     <xsl:variable name="vDefaults" select="document('')/*/my:defaults"/>
    
     <xsl:template match="/">
         <xsl:value-of select=
         "(/Foo/Baz 
           | $vDefaults/Foo/Baz[not(current()/Foo/Baz/text())]
           )
            [last()]"/>
     </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2020-12-05 06:05

    If you are okay with printing an empty string instead of 'not-found' message then use:

    /Foo/concat(Baz/text(), '')
    

    Later, you can replace the empty strings with 'not-found'.

    0 讨论(0)
  • 2020-12-05 06:14

    In XPath 1.0, use:

    concat(/Foo/Baz,
           substring('not-found', 1 div not(/Foo/Baz)))
    

    If you want to handle the posible empty Baz element, use:

    concat(/Foo/Baz,
           substring('not-found', 1 div not(/Foo/Baz[node()])))
    

    With this input:

    <Foo>
        <Baz/>
    </Foo>
    

    Result: not-found string data type.

    0 讨论(0)
  • 2020-12-05 06:19

    Special case: If you want to get 0 if numeric node is missing or empty, use sum(/Foo/Baz) function

    0 讨论(0)
提交回复
热议问题