0
votes

I'm trying to exclude some elements from an XML input using XPath. In the following sample, I need to exclude all "X" elements.

I thought I just have to use a XPath query like //*[not(self::X)] but this seems to not be working on all platforms.

I tried in those 2 websites:

http://chris.photobooks.com/xml/default.htm

http://www.freeformatter.com/xpath-tester.html

For the 1st one, the xml output would be as expected (X elements are not highlighted in the output) but for the 2nd one, the output is strictly the same as the input. Unfortunately, the software that will use this XPath has the same behaviour as the 2nd website...

Other strange thing: when I try //*[self::X], I get all X elements on both sites.

Can you help me for this simple request? I may be missing something evident, but I'm quite new on XPath queries! Thanks.

Sample:

<ROOTNODE>
    <ITEM>12345</ITEM>
    <LEVELS COUNT="1">
        <LEVEL>
            <OFFICES COUNT="3">
                <OFFICE>
                    <CODEOFF>21</CODEOFF>
                    <LIB>GALLEY AVANT</LIB>
                    <NIV>1</NIV>
                    <X>6</X>
                    <Y>78</Y>
                    <L>127</L>
                    <H>196</H>
                    <OBJECTS COUNT="7">
                        <OBJECT>
                            <CODEOBJ>G1C</CODEOBJ>
                            <LIB>GALLEY 1C</LIB>
                            <NIV>1</NIV>
                            <X>12</X>
                            <Y>143</Y>
                            <L>32</L>
                            <H>49</H>
                        </OBJECT>
                        <OBJECT>
                            <CODEOBJ>G1L</CODEOBJ>
                            <LIB>GALLEY 1L</LIB>
                            <NIV>1</NIV>
                            <X>32</X>
                            <Y>205</Y>
                            <L>34</L>
                            <H>29</H>
                        </OBJECT>
                    </OBJECTS>
                </OFFICE>
            </OFFICES>
        </LEVEL>
    </LEVELS>
</ROOTNODE>
2

2 Answers

3
votes

You cannot do this with XPath.

XPath can only select whole subtrees, not modify them / construct new results. Either you need to use XQuery or use some DOM interface to select and delete the <X/> elements (which you could find by using the XPath query //X).

2
votes

XPath selects nodes from the tree representation of the input document. Think of it returning pointers into the tree data structure, if you like.

Whatever software you are using to display the XPath results then has to decide how to display these "pointers". The most usual convention is to display the whole XML tree rooted at the node that you selected. This isn't the only way to do it; some tools prefer to display a path from the root to the selected node. But the important thing is to distinguish what XPath is selecting (a node), from the way it is being displayed (showing the whole subtree, or the path from the root).

If you want your output to contain different XML from your input, then you're out of luck with XPath. To do that, you need XSLT or XQuery. XPath strictly selects nodes from the input tree.