10 Replies Latest reply: May 20, 2011 2:50 AM by danieldk RSS

    Matching children attributes with XPath

    danieldk
      We use XML documents that representing (parse) trees. Each node of the tree, aptly named word, represents some category (@cat) with the attribute and has some beginning and end position (@begin/@end). In our application we are restricted to XPath, because that is the query interface for the user.

      Now, suppose that we'd like to find a node with two children, for which the following is true:

      - Both nodes have the category 'np'.
      - The end position of one node is the begin position of the other node.

      In our huge collection of trees, such cases occur fairly often.

      To find such nodes, we use the following query:

      //node[node[@cat="np"]/@end = node[@cat="np"]/@begin ]

      Now, if I enter this query in the xquery command:

      query 'collection("cdb.dact")//node[node[@cat="np"]/@end = node[@cat="np"]/@begin ]'

      I get zero results. Most other queries work as expected. Using the XPath functionality of libxml2 does return the correct nodes for this query.

      Any ideas what might be wrong?

      Edited by: 859889 on May 18, 2011 12:37 PM
        • 1. Re: Matching children attributes with XPath
          637288
          Hi,

          in what namespace are your documents/nodes? The query you've provided would work only if your "node" elements have no namespace bound to them.

          Maybe the following query will work?
          query 'collection("cdb.dact")//node[node[@cat="np"]/@end/string(.) = node[@cat="np"]/@begin/string(.) ]'
          Vyacheslav
          • 2. Re: Matching children attributes with XPath
            danieldk
            detonator413 wrote:
            in what namespace are your documents/nodes? The query you've provided would work only if your "node" elements have no namespace bound to them.
            They are not in a namespace.
            Maybe the following query will work?
            query 'collection("cdb.dact")//node[node[@cat="np"]/@end/string(.) = node[@cat="np"]/@begin/string(.) ]'
            Indeed, that works. Thanks! Do you have any idea why this works, but the query above doesn't?
            • 3. Re: Matching children attributes with XPath
              danieldk
              Another datapoint: when I apply the query to plain XML files with XQilla I do get matches.

              I am a bit worried by the query plan. The query plan of the working query [1] is:
              <XQuery>
                <QueryPlanToAST>
                  <PredicateFilterQP>
                    <StepQP axis="descendant" name="node" nodeType="element">
                      <SequentialScanQP container="cdb.dact" nodeType="document"/>
                    </StepQP>
                    <Operator name="equal">
                      <Map>
                        <QueryPlanToAST>
                          <NodePredicateFilterQP uri="" name="#tmp2">
                            <StepQP axis="child" name="node" nodeType="element">
                              <ContextNodeQP/>
                            </StepQP>
                            <AttributeJoinQP>
                              <VariableQP name="#tmp2"/>
                              <ValueQP container="cdb.dact" index="node-attribute-equality-string" operation="eq" child="cat" value="np"/>
                            </AttributeJoinQP>
                          </NodePredicateFilterQP>
                        </QueryPlanToAST>
                        <Function name="{http://www.w3.org/2005/xpath-functions}:string">
                          <TreatAs>
                            <QueryPlanToAST>
                              <StepQP axis="attribute" name="begin" nodeType="attribute">
                                <ContextNodeQP/>
                              </StepQP>
                            </QueryPlanToAST>
                            <SequenceType type="item()?"/>
                          </TreatAs>
                        </Function>
                      </Map>
                      <Map>
                        <QueryPlanToAST>
                          <NodePredicateFilterQP uri="" name="#tmp6">
                            <StepQP axis="child" name="node" nodeType="element">
                              <ContextNodeQP/>
                            </StepQP>
                            <AttributeJoinQP>
                              <VariableQP name="#tmp6"/>
                              <ValueQP container="cdb.dact" index="node-attribute-equality-string" operation="eq" child="cat" value="np"/>
                            </AttributeJoinQP>
                          </NodePredicateFilterQP>
                        </QueryPlanToAST>
                        <Function name="{http://www.w3.org/2005/xpath-functions}:string">
                          <TreatAs>
                            <QueryPlanToAST>
                              <StepQP axis="attribute" name="end" nodeType="attribute">
                                <ContextNodeQP/>
                              </StepQP>
                            </QueryPlanToAST>
                            <SequenceType type="item()?"/>
                          </TreatAs>
                        </Function>
                      </Map>
                    </Operator>
                  </PredicateFilterQP>
                </QueryPlanToAST>
              </XQuery>
              The plan of the problematic query [2] is:
              <XQuery>
                <QueryPlanToAST>
                  <StepQP axis="parent-of-child" name="node" nodeType="element">
                    <NodePredicateFilterQP uri="" name="#tmp18">
                      <StepQP axis="parent-of-attribute" name="node" nodeType="element">
                        <ValueQP container="cdb.dact" index="node-attribute-equality-string" operation="eq" child="cat" value="np"/>
                      </StepQP>
                      <NodePredicateFilterQP>
                        <StepQP axis="attribute" name="begin" nodeType="attribute">
                          <VariableQP name="#tmp18"/>
                        </StepQP>
                        <IntersectQP>
                          <ContextNodeQP/>
                          <ValueQP container="cdb.dact" index="node-attribute-equality-string" operation="eq" child="begin">
                            <Atomize>
                              <QueryPlanToAST>
                                <StepQP axis="attribute" name="end" nodeType="attribute">
                                  <NodePredicateFilterQP uri="" name="#tmp2">
                                    <StepQP axis="child" name="node" nodeType="element">
                                      <ContextNodeQP/>
                                    </StepQP>
                                    <AttributeJoinQP>
                                      <VariableQP name="#tmp2"/>
                                      <ValueQP container="cdb.dact" index="node-attribute-equality-string" operation="eq" child="cat" value="np"/>
                                    </AttributeJoinQP>
                                  </NodePredicateFilterQP>
                                </StepQP>
                              </QueryPlanToAST>
                            </Atomize>
                          </ValueQP>
                        </IntersectQP>
                      </NodePredicateFilterQP>
                    </NodePredicateFilterQP>
                  </StepQP>
                </QueryPlanToAST>
              </XQuery>
              Shouldn't there be an equality 'Operator' in the second case as well? However, I am not familiar with the query plan notation.

              [1] collection("cdb.dact")//node[node[@cat="np"]/string(@begin) = node[@cat="np"]/string(@end)]
              [2] collection("cdb.dact")//node[node[@cat="np"]/@begin = node[@cat="np"]/@end

              Edited by: danieldk on May 19, 2011 2:15 AM

              Edited by: danieldk on May 19, 2011 2:17 AM
              • 4. Re: Matching children attributes with XPath
                danieldk
                By the way, if anyone wants to try this out, the container can be found at:

                http://www.let.rug.nl/~dekok/corpora/cdb.dact.gz

                The query should match 292 times in 286 documents.
                • 5. Re: Matching children attributes with XPath
                  637288
                  Hi,

                  I will look into it soon, just to let you know

                  Vyacheslav
                  • 6. Re: Matching children attributes with XPath
                    637288
                    Hi,

                    I think that it's a bug in DB XML that query [2] does not return any values.

                    In query [2] you use a general comparison for a sequence of attribute nodes. According to the specification, this sequence should be atomized first, i.e. for every attribute node its typed value should be extracted. In your case since you don't have XML Schema, a typed value is equal to a string value. Thus [2] is equivalent to [1].

                    Vyacheslav
                    • 7. Re: Matching children attributes with XPath
                      danieldk
                      Thanks, indeed, it seems to be a bug. Where do I report this?
                      • 8. Re: Matching children attributes with XPath
                        637288
                        Hi,

                        I'm not a DB XML developer, but AFAIK Oracle has no public bug trackers. Eventually, one of DB XML developers typically will read this forum post and confirm that it is a bug and enter a ticket.

                        Vyacheslav
                        • 9. Re: Matching children attributes with XPath
                          655560
                          Hi danieldk,

                          I entered a ticket for this issue and will take a look into it. Thanks for your reporting.

                          For now, please just use the workaround which Vyacheslav suggested. Thanks.

                          Best regards,
                          Rucong
                          Oracle Berkeley DB XML
                          • 10. Re: Matching children attributes with XPath
                            danieldk
                            Thanks Rucong!