XPATH选择整个树只包括第一个

时间:2012-09-27 14:21:14

标签: xslt xpath

给定以下结构,在XPATH中,我想选择整个树,但只包括第一个日期,因此排除所有其他日期。第一个日期之后的日期数不是恒定的。有任何想法吗?我的道歉是格式不正确。

<A>
    <B>
        <DATE>04272011</DATE>
        <C>
           <D>
                <DATE>02022011</DATE>
           </D>
           <D>
                <DATE>03142011</DATE>
           </D>
        </C>
    </B>
</A>

我的抱歉。

更好的例子

<NOTICES>

<SNOTE>

    <DATE>01272011</DATE>
    <ZIP>35807</ZIP>
    <CLASSCOD>A</CLASSCOD>
    <EMAIL>
        <ADDRESS>address 1</ADDRESS>
    </EMAIL>
    <CHANGES>
        <MOD>
            <DATE>02022011</DATE>
            <MODNUM>12345</MODNUM>
            <EMAIL>
                <ADDRESS>address 2</ADDRESS>
            </EMAIL>
        </MOD>
        <MOD>
            <DATE>03022011</DATE>
            <MODNUM>56789</MODNUM>
            <EMAIL>
                <ADDRESS>address 3</ADDRESS>
            </EMAIL>
        </MOD>
    </CHANGES>
</SNOTE>

</NOTICES>

我将一个大型xml文件分解为单个XML文件。我最初的XPATH语句是

/通知/ S注

除了拉入所有日期外,每个单独的xml文件看起来都很好:这是我想要的输出。

<SNOTE>

<DATE>01272011</DATE>
<ZIP>35807</ZIP>
<CLASSCOD>A</CLASSCOD>
<EMAIL>
    <ADDRESS>address 1</ADDRESS>
</EMAIL>
<CHANGES>
    <MOD>
        <MODNUM>12345</MODNUM>
        <EMAIL>
            <ADDRESS>address 2</ADDRESS>
        </EMAIL>
    </MOD>
    <MOD>
        <MODNUM>56789</MODNUM>
        <EMAIL>
            <ADDRESS>address 3</ADDRESS>
        </EMAIL>
    </MOD>
</CHANGES>

</SNOTE>

2 个答案:

答案 0 :(得分:3)

XPath是XML文档的查询语言,因此它不能改变文档的结构(例如插入/删除/重命名节点)。

您需要的是XSLT转换 - 就像这个简单

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="DATE[preceding::DATE]"/>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<A>
    <B>
        <DATE>04272011</DATE>
        <C>
            <D>
                <DATE>02022011</DATE>
            </D>
            <D>
                <DATE>03142011</DATE>
            </D>
        </C>
    </B>
</A>

产生了想要的正确结果

<A>
   <B>
      <DATE>04272011</DATE>
      <C>
         <D/>
         <D/>
      </C>
   </B>
</A>

答案 1 :(得分:1)

如果通过“选择整个树”意味着“选择树中所有节点的集合”(非第一个DATE元素除外),可以这样做:

"//node()[not(self::DATE) or not(preceding::DATE)]"

然后,非第一个<DATE>元素节点本身不会位于所选节点集中,但所选节点集中的节点(例如根节点或<D>)仍将具有{{ 1}}后代。

如果你想要选择树(即根节点),或者更确切地说是它的修改版本,那么<DATE>个元素没有任何<D>子元素,则需要修改那个树。 XPath无法自行修改XML树。您需要XML转换技术,例如XSLT或XML DOM库。