Question

I have an xml:

<Customer id="">
 <Name />
 <Address />
</Customer>

I would like to select ONLY a root node with its attributes without its child nodes:

<Customer id=""/ >

Is such thing possible with XPath?

Was it helpful?

Solution

No, this is not possible in XPath.

You can't select the node without its children, because without its children it would be a different node, hence you would not be selecting a node from the original document.

To create the output you want you need to use a language which allows you to create new nodes, so you can't do it in XPath. You can use XQuery to create new nodes, this should work:

element {fn:node-name(/*)} {/*/@*}

OTHER TIPS

XPath does not alter any source XML document and this is by design.

To produce a new XML document from an existing one, transformation is needed.

XSLT has been especially designed for transforming a set of trees (including XML documents) into result trees.

This transformation:

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

    <xsl:template match="/*">
      <xsl:copy>
       <xsl:copy-of select="@*"/>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<Customer id="">
    <Name />
    <Address />
</Customer>

produces the wanted, correct result:

<Customer id=""/>
$doc = new DOMDocument();
$doc->loadHTML($str);

$xPath = new DOMXpath($doc);
$xPathQuery = "//text()[contains(translate(.,'abcdefghijklmnopqrstuvwxyz',  'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), '<Customer id=\"\">')]";
$elements = $xPath->query($xPathQuery);

if($elements->length > 0){

foreach($elements as $element){
    print "Found: " .$element->nodeValue."<br />";
}

This XQuery expression:

element {name(/*)} {/*/@*}

Output:

<?xml version="1.0" encoding="UTF-8"?><Customer id=""/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top