7

我正在编写一个 xslt 样式表来将一个 xml 转换为另一个 xml。

这是原始xml的简化版本:

 <eml>
        <datatable>
                 <physical>
                     <distribution id="100"/>
                 </physical>
       </datatable>                 

       <software>
           <implementation>
              <distribution id="200"/>
            </implementation>
      </software>
     <additionalMetadata>
        <describes>100</describes>
        <describes>200</describes>
        <describes>300</describes>
        <describes>400</describes>
    </additionalMetadata>
   </eml>

我尝试使用 Xpath 来选择“描述”的节点集,该节点集的值不等于//physical/distributionor的 id 值software/implementation/distribution。在上述情况下,我想获取节点集:

   <deseribes>300</describes>
   <deseribes>400</describes>

(100 和 200 是//physical/distributionor 的属性 id 值software/implementation/distribution)。

我写了类似的东西:

<xsl:with-param name="describes-list" 
                select="./describes[//physical/distribution/@id !=. and
                             //software/implementation/distribution/@id != .] "/>

它适用于上述示例。但是,数据表和软件的元素是可重复的。所以这个xml是有效的:

<eml>
    <datatable>
             <physical>
                 <distribution id="100"/>
             </physical>
   </datatable> 

  <datatable>
             <physical>
                 <distribution id="300"/>
             </physical>
   </datatable>                

   <software>
       <implementation>
          <distribution id="200"/>
       </implementation>
  </software>
 <additionalMetadata>
    <describes>100</describes>
    <describes>200</describes>
    <describes>300</describes>
    <describes>400</describes>
  </additionalMetadata>
</eml>

但是我的 xslt 不适用于上面的例子:(

你介意对此有所了解吗?先感谢您!

4

1 回答 1

20

这是一个经常犯的错误。当一个或两个操作数是/是节点集时,切勿使用XPath 的“!=”运算符。

   value != node-set

如果在节点集中存在节点 n,则根据定义为真,这样

   value不等于string(n)

你想要的是

   value不等于节点集中的任何节点。

这可以用以下方式表示:

   value = node-set

如果在节点集中至少存在一个节点 n,则为真,这样:

   value = string(n)

然后

   not(value = node-set)

如果节点集中不存在任何节点 n 则为真,这样

   value = string(n)

因此,以下 XPath 表达式将选择所需的节点

/*/*/describes[not(. = ../../*/physical/distribution/@id)
              和
                不(。= ../../*/实施/分发/@id)]

我个人更愿意将上下文节点与两个节点集的并集进行一次比较:

/*/*/描述
            [not(. = (../../*/physical/distribution/@id
                    |
                      ../../*/实施/分发/@id
                     )
                 )
            ]

请注意,我避免使用“//”缩写。它通常非常昂贵(效率低​​下),只有在我们不知道 XML 文档的结构时才应该使用它。

当然,上面的 XPath 表达式必须针对以下 XML 文档(问题中提供的第二个文档)进行评估:

<emml>
    <数据表>
        <物理>
            <distribution id="100"/>
        </物理>
    </数据表>
    <数据表>
        <物理>
            <distribution id="300"/>
        </物理>
    </数据表>
    <软件>
        <实施>
            <distribution id="200"/>
        </实现>
    </软件>
    <附加元数据>
        <描述>100</描述>
        <描述>200</描述>
        <描述>300</描述>
        <描述>400</描述>
    </附加元数据>
</eml>
于 2008-12-02T00:01:59.847 回答