如何使用XPath选择非空兄弟节点的Cartesian Product集?

时间:2013-12-19 16:46:39

标签: xml xpath xpath-2.0 altova

这是第一次发布海报,所以如果我做错了,请不要犹豫,告诉我。

我正在使用Altova Stylevision打印表单文档,我需要为每个独特的两个节点集合打印表单的副本。下面是一个示例XML,以便更好地解释我的要求。

<form>
    <Animals>
        <Animal>
            <AName>Boomer</AName>
            <AAddress>House</AAddress>
        </Animal>
        <Animal>
            <AName>Growl</AName>
            <AAddress>Street</AAddress>
        </Animal>
        <Animal>
            <AName>Incognito</AName>
            <AAddress>Nowhere</AAddress>
        </Animal>
    </Animals>
    <People>
        <Person>
            <PName>Willy</PName>
            <PAddress>123 Common Lane</PAddress>
        </Person>
        <Person>
            <PName>Wonka</PName>
            <PAddress>Chocolate Factory</PAddress>
        </Person>
    </People>
</form>

我想从上面的示例中生成6个唯一值(笛卡尔积),其中包含<Animal><Person>的每个组合,其中它们都不为空。所以,这个例子的输出就像(只显示分组,需要所有子节点而不仅仅是名称):

([Boomer, Willy], [Boomer, Wonka], [Growl, Willy], [Growl, Wonka], [Incognito, Willy], [Incognito, Wonka])

编辑:我正在尝试获取节点,而不仅仅是<Name>元素值。因为我将整个StyleVision表单包装在此模板中,所以范围应该是<Animal><Person>级别。这样,我可以在表单中/AName, /PName,说出/AName/PName在表单的每个副本上获得一个值。它应该充当元素节点的6个实例,每个实例代表<Person><Animal>的唯一组合。

我查看了for # in # return语法,但我无法弄清楚如何返回唯一集。以下是我到目前为止所尝试的内容:

for $a in form/Animals/Animal, $p in form/People/Person return ($a, $p)

form/Animals/Animal | form/People/Person

有人能指出我正确的方向吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

<强>更新

您的for表达式是正确的,您只需添加一个元素构造函数即可获得所需的结果:

for $animal in $x/Animals/Animal,
    $person in $x/People/Person
return element union { $animal, $person }

元素名称(示例中为union)可以是您想要的任何内容。


这些原始代码示例将生成问题的结果字符串。

这有点难以阅读,但这会做你想要的:

concat("(",
  concat(string-join(
    for $animal in /form/Animals/Animal/Name,
        $person in /form/People/Person/Name
    return concat("[", concat(string-join(($animal, $person), ", "), "]")), ", "), ")"))

如果你可以使用XPath / XQuery 3.0处理器,你可以使用||连接运算符而不是concat函数调用,这在某种程度上更具可读性:

"(" ||
  string-join(
    for $animal in /form/Animals/Animal/Name,
        $person in /form/People/Person/Name
    return "[" || string-join(($animal, $person), ", ") || "]"
    , ", ")
|| ")"