1

给定以下结构,在 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 语句是

/通知/通知

每个单独的 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>

4

2 回答 2

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>
于 2012-09-27T16:09:41.623 回答
1

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

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

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

相反,如果您想选择树(即根节点),或者更确切地说是它的修改版本,使得<D>元素没有任何子节点<DATE>,那么这需要修改树。XPath 不能自己修改 XML 树。您需要 XML 转换技术,例如 XSLT 或 XML DOM 库。

于 2012-09-27T16:06:29.513 回答