如何使用XQuery以逗号分隔的格式基于多个条件提取特定的XML记录?

如何使用XQuery以逗号分隔的格式基于多个条件提取特定的XML记录?,xml,xquery,Xml,Xquery,输入文件: <?xml version="1.0" encoding="UTF-8"?> <books> <book id="6636551"> <master_information> <book_xref> <xref type="Fiction" type_id="

输入文件:

<?xml version="1.0" encoding="UTF-8"?> 
        <books>
            <book id="6636551">
                <master_information>
                    <book_xref>
                        <xref type="Fiction" type_id="1">72771KAM3</xref>
                        <xref type="Non_Fiction" type_id="2">US72771KAM36</xref>
                    </book_xref>
                </master_information>
                <book_details>
                    <price>24.95</price>
                    <publish_date>2000-10-01</publish_date>
                    <description>An in-depth look at creating applications with XML.</description>
                </book_details>
                <global_information>
                    <ratings>
                        <rating agency="ABC Agency" type="Author Rating">A++</rating>
                        <rating agency="DEF Agency" type="Author Rating">A+</rating>
                        <rating agency="DEF Agency" type="Book Rating">A</rating>
                    </ratings>
                </global_information>
                <country_info>
                    <country_code>US</country_code>
                </country_info>
            </book>
            <book id="119818569">
                <master_information>
                    <book_xref>
                        <xref type="Fiction" type_id="1">070185UL5</xref>
                        <xref type="Non_Fiction" type_id="2">US070185UL50</xref>
                    </book_xref>
                </master_information>
                <book_details>
                    <price>19.25</price>
                    <publish_date>2002-11-01</publish_date>
                    <description>A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.</description>
                </book_details>
                <global_information>
                    <ratings>
                        <rating agency="ABC Agency" type="Author Rating">A+</rating>
                        <rating agency="ABC Agency" type="Book Rating">A</rating>
                        <rating agency="DEF Agency" type="Author Rating">A</rating>
                        <rating agency="DEF Agency" type="Book Rating">B+</rating>
                    </ratings>
                </global_information>
                <country_info>
                    <country_code>CA</country_code>
                </country_info>
            </book>
            <book id="119818568">
                <master_information>
                    <book_xref>
                        <xref type="Fiction" type_id="1">070185UK7</xref>
                        <xref type="Non_Fiction" type_id="2">US070185UK77</xref>
                    </book_xref>
                </master_information>
                <book_details>
                    <price>5.95</price>
                    <publish_date>2004-05-01</publish_date>
                    <description>After the collapse of a nanotechnology society in England, the young survivors lay the foundation for a new society.</description>
                </book_details>
                <global_information>
                    <ratings>
                        <rating agency="ABC Agency" type="Author Rating">A+</rating>
                        <rating agency="ABC Agency" type="Book Rating">A+</rating>
                        <rating agency="DEF Agency" type="Author Rating">B++</rating>
                        <rating agency="DEF Agency" type="Book Rating">A+</rating>
                    </ratings>
                </global_information>
                <country_info>
                    <country_code>UK</country_code>
                </country_info>
            </book>
            <book id="119818567">
                <master_information>
                    <book_xref>
                        <xref type="Fiction" type_id="1">070185UJ0</xref>
                        <xref type="Non_Fiction" type_id="2">US070185UJ05</xref>
                    </book_xref>
                </master_information>
                <book_details>
                    <price>4.95</price>
                    <publish_date>2000-09-02</publish_date>
                    <description>When Carla meets Paul at an ornithology conference, tempers fly as feathers get ruffled.</description>
                </book_details>
                <global_information>
                    <ratings>
                        <rating agency="ABC Agency" type="Author Rating">B+</rating>
                        <rating agency="ABC Agency" type="Book Rating">A+</rating>
                        <rating agency="DEF Agency" type="Author Rating">B++</rating>
                        <rating agency="DEF Agency" type="Book Rating">A+</rating>
                    </ratings>
                </global_information>
                <country_info>
                    <country_code>US</country_code>
                </country_info>
            </book>
        </books>
预期产出为:

book_id, xref_type, xref, country, desc, rating_agency, rating_type, rating
6636551,Fiction,72771KAM3,US,An in-depth look at creating applications with XML.,DEF Agency,Author Rating,A+
6636551,Non_Fiction,US72771KAM36,US,An in-depth look at creating applications with XML.,DEF Agency,Author Rating,A+
119818569,Fiction,070185UL5,CA,A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.,ABC Agency,Author Rating,A+
119818569,Non_Fiction,US070185UL50,CA,A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.,ABC Agency,Author Rating,A+
etc.
因为我没有对外部参照类型进行过滤,所以应该在单独的行中显示它们,所以我希望book_ID会重复,但事实并非如此。生成的输出如下所示:

book_id, xref_type, xref, country, desc, rating_agency, rating_type, rating
6636551,Fiction,Non_Fiction,72771KAM3,US72771KAM36,US,An in-depth look at creating applications with XML.,DEF Agency,Author Rating,A+
119818569,Fiction,Non_Fiction,070185UL5,US070185UL50,CA,A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.,ABC Agency,Author Rating,A+
当我对xref_type=“Fiction”进行过滤时,我必须同时对xref/@type和xref进行过滤。这是可行的,但有更好的方法吗

基本上,我的问题可以分为三个小问题:

  • 我怎样才能在列表中列出“虚构”和“非虚构”项目 同一给定图书id的单独行
  • 有没有更好的方法来编写此代码的条件
  • 当特定条件缺少数据时,如何以输出空白值的方式写入条件?这是自动完成的吗
  • 我感谢你的帮助

    在计算XPath表达式
    祖先::book//book_xref/xref/@type
    时,上下文是单个
    评级
    元素,结果是
    类型=“…”
    属性的序列。因此,当您组装CSV行时,祖先
    book
    元素的所有类型的图书引用都被视为一个值(可以是一个项目序列)

    如果要将每个项目分离到其单独的CSV行中,则必须使用例如
    for
    循环对序列进行递归迭代。我使用
    let
    和循环覆盖所有
    xref
    s将
    book
    绑定到一个变量:

    string-join(
      (
        'book_id, xref_type, xref, country, desc, rating_agency, rating_type, rating',
        for $rating in //book//global_information/ratings/rating[@type='Author Rating' and .=('A+','B++')]
        let $book := $rating/ancestor::book
        for $xref in $book//xref
        return (
          string-join(
            (
              $book/@id,
              $xref/@type,
              $xref/text(),
              $book//country_info/country_code,
              $book//book_details/description/text(),
              $rating/@agency,
              $rating/@type,
              $rating/text()
            ),
            ','
          )
        )
      ),
      '&#10;'
    )
    
    如果要避免向后轴(有时可能有点笨拙),也可以先迭代
    书籍
    s,然后迭代您感兴趣的
    评级
    s:

    string-join(
      (
        'book_id, xref_type, xref, country, desc, rating_agency, rating_type, rating',
        for $book in //book
        for $rating in $book/global_information/ratings/rating[@type='Author Rating' and .=('A+','B++')]
        for $xref in $book//xref
        [...]
    

    现在这很有道理。这太酷了!每次我在这里问问题,我都会学到更多。谢谢!非常感谢你的解释。可能是一个愚蠢的后续问题,但我如何才能过滤国家价值观?我像
    $book//country\u info/country\u code[数据[.='US','UK']].
    那样写它,但这不起作用。我也试过不用“数据”。直接过滤元素数据的正确方法是什么?第一次尝试时有几个问题。首先,如果编写
    $foo[x=$bar,$baz]
    ,则在谓词内部创建一个包含两部分的序列
    x=$bar
    ,和
    $baz
    。如果要匹配序列中的某个元素,则必须使用parens构建该序列:
    $foo[x=($bar,$baz)]
    。其次,
    data
    不是XQuery中的关键字。您可能指的是函数
    data()
    ,它返回上下文值的原子化(即非XML)内容。因此,一个解决方案是
    $book//country\u info/country\u code[data()[.=('US','UK')]]
    ,这很有意义$book//country\u info/country\u code[data()[.=('US','UK')]]以某种方式仅从输出中删除非英国或美国的所有国家/地区值-假设目标是过滤输出以包含仅与英国或美国相关的记录。你会怎么做?我尝试创建一个新的$book1,就像$book一样,但是包含国家代码的过滤器,但是它会以某种方式输出相同的图书id,并且两个国家代码在不同的行上。它正在增加价值!
    string-join(
      (
        'book_id, xref_type, xref, country, desc, rating_agency, rating_type, rating',
        for $book in //book
        for $rating in $book/global_information/ratings/rating[@type='Author Rating' and .=('A+','B++')]
        for $xref in $book//xref
        [...]