在xpath中设置节点

6 xml xslt xpath

我正在编写一个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>
Run Code Online (Sandbox Code Playgroud)

我尝试使用Xpath来选择"describe"的节点集,该节点集的值不等于//physical/distributionor 的id值software/implementation/distribution.在上面的例子中,我想得到节点集:

   <deseribes>300</describes>
   <deseribes>400</describes>
Run Code Online (Sandbox Code Playgroud)

(100和200是属性id值//physical/distributionsoftware/implementation/distribution).

我写了类似的东西:

<xsl:with-param name="describes-list" 
                select="./describes[//physical/distribution/@id !=. and
                             //software/implementation/distribution/@id != .] "/>
Run Code Online (Sandbox Code Playgroud)

它适用于上面的例子.但是,数据表和软件的元素是可重复的.所以这个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>
Run Code Online (Sandbox Code Playgroud)

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

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

Dim*_*hev 19

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

   value != node-set

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

   value 不等于 string(n)

你想要的是那个

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

这可以用以下方式表达:

   value = node-set

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

   value = string(n)

然后

   not(value = node-set)

如果节点集中不存在任何节点n,则为true

   value = string(n)

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

 /*/*/describes[not(. = ../../*/physical/distribution/@id)
              and 
                not(. = ../../*/implementation/distribution/@id)]

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

 /*/*/describes
            [not(. = (../../*/physical/distribution/@id
                    | 
                      ../../*/implementation/distribution/@id
                     )
                 )
            ]

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

当然,上述XPath表达式必须针对以下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>