How to query graphml using php, DomDocument and DomXPath? - php

Does someone know how to query a graphml document with php, DomDocument and DomXpath?
My query seems to be correct.
e.g. //graphml/graph/node
$dom = new DomDocument();
$dom->load("doc.graphml");
$x = new DOMXPath($dom);
$x->registerNamespace('y', "http://www.yworks.com/xml/graphml");
$r = $x->query("//graphml/graph/node");
echo $r->length;
The returned length is always 0;
But it has to be 1.
XML:
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:y="http://www.yworks.com/xml/graphml"
xmlns:yed="http://www.yworks.com/xml/yed/3"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yFiles for Java 2.8-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Beschreibung" attr.type="string" for="graph" id="d7">
<default/>
</key>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<node id="n0">
<data key="d4"><![CDATA[http://www.vilauma.de/]]></data>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="30.0" x="785.0" y="-15.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="internal" modelPosition="c" textColor="#000000" visible="true" width="45.349609375" x="-7.6748046875" y="5.6494140625">vilauma</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
</graph>
</graphml>

Solved my question!
$dom = new DomDocument();
$dom->load("doc.graphml");
$x = new DOMXPath($dom);
$x->registerNamespace("graphml", "http://graphml.graphdrawing.org/xmlns");
$r = $x->query("//graphml:node");
echo $r->length; // result => 1

Related

XML file/data handling with PHP

I have a XML file as a master file (master.xml) and its content is blank.
<?xml version="1.0" encoding="UTF-8"?>
<master/>
I have a loop in which i get some data and turn them into xml files (item.xml) and their content is like
<?xml version="1.0" encoding="UTF-8"?>
<master>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
</master>
All i want, is to be able to get the Item from the item.xml and insert it on master.xml under the master tag so the final result would look something like
<?xml version="1.0" encoding="UTF-8"?>
<master>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
</master>
I don't know if it helps but the code right now is like this.
$targetDom = new DOMDocument();
$targetDom->load('master.xml');
while($row = $sql->fetch(PDO::FETCH_ASSOC)) {
// Data beeing processed and stored as item.xml
$sourceDom = new DOMDocument();
$sourceDom->load('item.xml');
foreach ($sourceDom->documentElement->childNodes as $child) {
$targetDom->appendChild(
$targetDom->importNode($child, TRUE)
);
}
}
The code above has a result of this
<?xml version="1.0" encoding="UTF-8"?>
<master/>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
<item>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</item>
What am i missing?
You need to append the items to the first element of the $targetDom
Use:
$targetDom->documentElement->appendChild(
$targetDom->importNode($child, TRUE)
);

How to get all nodes with xpath and return as resposeXML to js?

How to retrieve xml using xpath and send back to client js as responseXML?
I have php as the server, js as the client, need the specified data and display as html table.
here's my xml
// goods.xml
<items>
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>3</id>
<itemname>Apple iPhone 8</itemname>
<itemqty>2</itemqty>
</item>
</items>
I want those item with over 10 quantities, I was only able to get only one of them with my php file
// handle.php
$xmlFile = "../../data/goods.xml";
$doc->load($xmlFile);
$xpath = new DOMXPath($doc);
$xml = new SimpleXMLElement($xmlFile, NULL, TRUE);
$nodes = $xml->xpath("/items/item[itemqty>10]");
echo $doc->saveXML($xpathresultset->item(0)); // send the xml response back to the client
Then I only got the first result, I couldn't get both result (id 1 & id 2)
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
But I want
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
Any help would be appreciated!!
This is probably more easily done using DOMDocument than SimpleXML, as you can then use xpath to search for nodes with itemqty <= 10 and remove them from the document:
$xml = '<items>
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>3</id>
<itemname>Apple iPhone 8</itemname>
<itemqty>2</itemqty>
</item>
</items>';
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
foreach ($xpath->query('/items/item[itemqty<=10]') as $node) {
$node->parentNode->removeChild($node);
}
echo $doc->C14N();
Output:
<items>
<item>
<id>1</id>
<itemname>Apple iPhone X</itemname>
<itemqty>20</itemqty>
</item>
<item>
<id>2</id>
<itemname>Apple iPhone 7</itemname>
<itemqty>20</itemqty>
</item>
</items>

Incorrect PHP SOAP Formatting

I am trying to make use of the stand soapClient for PHP. I can make a class successfully using SOAP UI however when I trry and make that call using PHP this is the difference.
<arrInputs xsi:type="ns1:KeyValueArrayInput" SOAP-ENC:arrayType="ns1:KeyValueArray[]" >
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">Realm</Key>
<Value xsi:type="xsd:string">test</Value>
</item>
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">UserName</Key>
<Value xsi:type="xsd:string">test15</Value>
</item>
Now when I try send it via the php soap client I get this.
<arrInputs SOAP-ENC:arrayType="ns1:KeyValueArray[22]" xsi:type="ns1:KeyValueArrayInput">
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">Realm</Key>
<Value xsi:type="xsd:string">test</Value>
</item>
<item xsi:type="ns1:KeyValueArray">
<Key xsi:type="xsd:string">UserName</Key>
<Value xsi:type="xsd:string">test2</Value>
</item>
Any suggestions as to how the type and the array type have been switched around. If I put the type in front of the arrayType all is good.
$creationFields = array();
$creationFields['strSessionID'] = $this->getSessionHash();
$arrInputs = array();
foreach ($params as $k => $v)
{
$arrInputs[] = array('Key' => $k, 'Value' => $v);
}
$creationFields['arrInputs'] = $arrInputs;
__soapCall('methodName', $creationFields);
This is out of the WSDL:
<message name="methodName"><part name="strSessionID" type="xsd:string" /><part name="arrInputs" type="tns:KeyValueArrayInput" /></message>

need help.. php soap

I have a xml document, i need to get name attribute's value with helping php. the xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:GetGoodsTreeResponse xmlns:ns2="http://b2b.alta.com.ge" xmlns:ns3="http://192.168.0.10/b2b">
<ns3:GoodsTree level="0">
<item id="010000000017337" level="0" name="COMPUTERS" is_open="N">
<item id="015000000030431" level="1" name="ALTA" is_open="Y">
<item id="015000000030443" level="2" name="Zakaznoe Izdelie" is_open="N"/>
<item id="015002000031034" level="2" name="ATOM" is_open="N"/>
<item id="015005000030453" level="2" name="Celeron" is_open="N"/>
<item id="015010000030432" level="2" name="Dual Core" is_open="N"/>
<item id="015150000030778" level="2" name="i3" is_open="N"/>
<item id="015220000030775" level="2" name="i5" is_open="N"/>
<item id="015300000031827" level="2" name="i7" is_open="N"/>
</item>
<item id="010001005030300" level="1" name="Apple" is_open="N"/>
<item id="010001001033496" level="1" name="Asus" is_open="N"/>
<item id="010001001015793" level="1" name="Fujitsu" is_open="N"/>
<item id="010001002015166" level="1" name="HP Compaq" is_open="N"/>
</item>
</ns3:GoodsTree>
</ns2:GetGoodsTreeResponse>
</S:Body>
</S:Envelope>
please help me i dont know what to do.. sorry for my english.
You can use DOMDocument to parse that XML and get all items using DOMXpath, then loop in all items and get the attributes based on position (id = 0, name = 2), then create an new array that will hold all you item id's with their names:
$dom = new DOMDocument;
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('S', 'http://schemas.xmlsoap.org/soap/envelope/');
$items = array();
$el = $xpath->query('//item');
foreach($el as $item){
$attributes = $item->attributes;
$items[$attributes->item(0)->value] = $attributes->item(2)->value;
}
var_dump($items); // $items will be an array with item id and it's value will be item name
Codepad Example

php soapserver returning better readable associative array

I'm using PHP SOAPSERVER class.
As a response I'm sending associative php array:
function getItems()
{
...
$items[] = Array("itemID" =>$itemID,"itemName"=>$itemName);
return $items;
}
SOAP return is like this:
...
<Items>
<item type="Map">
<item>
<key type="string">
itemID
</key>
<value type="string">
17558
</value>
</item>
<item>
<key type="string">
itemName
</key>
<value type="string">
I-17558
</value>
</item>
</item>
</Items>
...
Such return is pretty hard to analyze for human (given bigger array).
The preferred form would be like this:
...
<Items>
<item>
<itemID>17558</itemID>
<itemName>I-17558</itemName>
</item>
<item>
<itemID>17559</itemID>
<itemName>I-17559</itemName>
</item>
</Items>
...
Is such SOAP return possible (not changing the return type - array)? How?
I have just started with SOAP and most tutorials show how to return simple types like string.
Instead of sending an associative array, send a stdclass object.
Example :
$return = new stdclass;
$return->ItemID = 1;
$return->ItemName = 'foo';
return $return;
Then the SOAP results will be just the way you want it!

Categories