从两个相关的xml文件中获取节点值

时间:2013-11-27 09:03:53

标签: xpath xquery altova

我是Xquery的初学者,我有一个xml代码,我希望将两个不同的XML文件与另一个文件相关联。

Book.xml

<library>
   <Book>
     <title>Title1</title>
     <author>Ellizabith</author>
   </Book>
   <Book>
     <title>Title2</title>
     <author>Sam</author>
   </Book>
   <Book>
    <title>Title3</title>
    <author>Ryan</author>
   </Book>
</library>

author.xml

 <authorRoot>
   <author>
    <Name>Rayan</Name>
     <Location>Yahoo</Location>
    </author>
    <author>
      <Name>Syan</Name>
      <Location>Google</Location>
    </author>
    <author>
      <Name>Sam</Name>
      <Location>Bing</Location>
     </author>
    </authorRoot>

在此回答一个查询,以显示标题中包含“Title2”一词的书籍的所有作者的位置。

这是我的代码:

 for $p in doc("C:\Users\User\Desktop\Book.xml")//library/book/[title/contains(.,   'Title1')]
 for $a in doc("C:\Users\User\Desktop\author.xml")//authorRoot
 let $p := $p/author/text()
 let $d := $a/author
 let $f := $d/text()=$p/Location/text()
 return $f

2 个答案:

答案 0 :(得分:3)

您的代码存在多个小问题。

  1. 作者和书籍中的名称XML文件不匹配。我想这只是一些错别字。
  2. 谓词属于轴步骤,而不属于它们自己(在第一行中删除book之后的斜杠)。
  3. XML和XQuery是大写敏感的! <Book/>使用大写字母B,所以在XQuery中也是这样,同样在第1行。
  4. 在第二行中,您循环遍历所有<authorRoot/>元素。请改用authorRoot/author
  5. 在第三行中,你隐藏了这本FLWOR表达式其余部分的书名$p,但你想在第五行再次使用这本书。最好使用另一个变量名。
  6. 如果您不需要,请更好地不要使用descendant-or-self - 步骤//(第一行和第二行)。这会降低性能。
  7. 我不明白你的过滤想法是在第三到第五行。与这个有效的解决方案比较。另外我使用了变量名称,不要把自己与不必要的短名称混淆。

    通过尊重$book函数替换$authorsdoc(...)

    for $book in $books//library/Book[title/contains(.,   'Title1')]
    for $author in $authors//authorRoot/author
    where $book/author = $author/Name
    return $author/Location/text()
    

    如果您想要一个不同位置的列表,请围绕所有四行包裹distinct-values(...)

    没有显式循环的替代方案:

    $authors/authorRoot/author[
      Name = $books/library/Book[contains(title, 'Title1')]/author)
    ]/Location
    

    第二种解决方案也是有效的XPath 1.0,第一种解决方案需要XPath 3.0或XQuery处理器。

答案 1 :(得分:2)

如果您使用

let $books := <library>
   <Book>
     <title>Title1</title>
     <author>Ellizabith</author>
   </Book>
   <Book>
     <title>Title2</title>
     <author>Sam</author>
   </Book>
   <Book>
    <title>Title3</title>
    <author>Ryan</author>
   </Book>
</library>
let $authors := <authorRoot>
   <author>
    <Name>Rayan</Name>
     <Location>Yahoo</Location>
    </author>
    <author>
      <Name>Syan</Name>
      <Location>Google</Location>
    </author>
    <author>
      <Name>Sam</Name>
      <Location>Bing</Location>
     </author>
     <author>
         <Name>Ellizabith</Name>
         <Location>Apple</Location>
    </author>
    </authorRoot>
    return $authors/author[Name = $books/Book[contains(title, 'Title1')]/author]/Location/string()

结果为Apple