(bash) Delete elements from xml if a value is missing - bash

I'd like to remove some elements in a big xml file, if a value is missing.
I have found a topic where it says how to extract the elements where the value is present but not the other way around. Solution could be sed or xmlstartlet but I can't figure it out.
xmlstarlet ed -d '//eslXmlDto[.//itemAssociations]' < file1.xml >> file2.xml
Here is the file I have
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<screens>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2017-04-25T12:23:18.746+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>16201000032884264000</screenCode>
<itemAssociations>
<itemCode>2118550000000</itemCode>
<position>1</position>
</itemAssociations>
</screenXmlDto>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2016-07-27T03:59:17.328+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>17201000030538183370</screenCode>
</screenXmlDto>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2016-07-26T12:28:20.815+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>17201000030538091000</screenCode>
<itemAssociations>
<itemCode>4008033444958</itemCode>
<position>1</position>
</itemAssociations>
</screenXmlDto>
</screens>
Here is the output I want
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<screens>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2017-04-25T12:23:18.746+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>16201000032884264000</screenCode>
<itemAssociations>
<itemCode>2118550000000</itemCode>
<position>1</position>
</itemAssociations>
</screenXmlDto>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2016-07-26T12:28:20.815+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>17201000030538091000</screenCode>
<itemAssociations>
<itemCode>4008033444958</itemCode>
<position>1</position>
</itemAssociations>
</screenXmlDto>
</screens>

xmlstarlet solution:
xmlstarlet ed -d '//screenXmlDto[not(itemAssociations)]' file1.xml
-d - delete action
//screenXmlDto[not(itemAssociations)] - xpath expression to select all screenXmlDto nodes which don't have itemAssociations node as a child
The output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<screens>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2017-04-25T12:23:18.746+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>16201000032884264000</screenCode>
<itemAssociations>
<itemCode>2118550000000</itemCode>
<position>1</position>
</itemAssociations>
</screenXmlDto>
<screenXmlDto>
<articleCodeType>EAN</articleCodeType>
<creationDate>2016-07-26T12:28:20.815+02:00</creationDate>
<domain>toto.tata</domain>
<screenCode>17201000030538091000</screenCode>
<itemAssociations>
<itemCode>4008033444958</itemCode>
<position>1</position>
</itemAssociations>
</screenXmlDto>
</screens>

Related

Mulesoft AMQP connector

Receving error Message : "org.mule.runtime.api.exception.MuleRuntimeException - Could not read from file store, while reading payload as Xml.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns:amqp="http://www.mulesoft.org/schema/mule/amqp"
xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/amqp http://www.mulesoft.org/schema/mule/amqp/current/mule-amqp.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<amqp:config name="AMQP_Config" doc:name="AMQP Config" doc:id="e0e4ca51-72e7-4d3b-bf01-705aacee16f0" >
<amqp:connection host="orangutan.rmq.cloudamqp.com" port="5672" virtualHost="xxxx" username="xxxx" password="xxxx" />
</amqp:config>
<flow name="artvanFlow" doc:id="59d15f19-3a12-491a-90a0-b2c980dbb05a" >
<amqp:listener doc:name="Listener" doc:id="ea9cb6d6-ccad-4a7f-8925-5879b561910e" config-ref="AMQP_Config" queueName="PIMQueue" outputMimeType="application/xml"/>
<ee:transform doc:name="Transform Message" doc:id="cddf8b22-91af-46b4-a8d6-c4237de75307" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
---
{
INVMSTP: {
IMDEL: payload.Root.STG_SKU.Activity_Code default ""
}
}]]></ee:set-payload>
</ee:message>
</ee:transform>
<logger level="INFO" doc:name="Logger" doc:id="a3411653-aff7-4363-8d24-6c10334d816f" message="#[payload]"/>
</flow>
</mule>
Apple to resolve the issue. There is no issue with the mule code. Input XML has
<?xml version="1.0" **encoding="WINDOWS-1251"** standalone="yes"?>
if I change to
<?xml version="1.0" **encoding="utf-8"** standalone="yes"?>
Things are fine.

How to retrieve all changed folders from the root public folder via EWS?

I need to get all public folders when a user changes permissions or items in a folder. How to do it? I can not find the proper answer in the documentation.
I only found this:
POST outlook.office365.com/EWS/Exchange.asmx
?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013" />
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:PrimarySmtpAddress>test#test_test.onmicrosoft.com</t:PrimarySmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<m:SyncFolderHierarchy>
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
</m:FolderShape>
<m:SyncFolderId>
<t:DistinguishedFolderId Id="publicfoldersroot" />
</m:SyncFolderId>
</m:SyncFolderHierarchy>
</soap:Body>
</soap:Envelope>
and the response is:
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="15" MinorVersion="20" MajorBuildNumber="1207" MinorBuildNumber="28" Version="V2018_01_08" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</s:Header>
<s:Body>
<m:SyncFolderHierarchyResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:SyncFolderHierarchyResponseMessage ResponseClass="Error">
<m:MessageText>The root of a folder hierarchy synchronization cannot be set to the id of a public folder. Use FindFolder to synchronize the public folder hierarchy.</m:MessageText>
<m:ResponseCode>ErrorInvalidOperation</m:ResponseCode>
<m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
<m:SyncState/>
<m:IncludesLastFolderInRange>true</m:IncludesLastFolderInRange>
</m:SyncFolderHierarchyResponseMessage>
</m:ResponseMessages>
</m:SyncFolderHierarchyResponse>
</s:Body>
</s:Envelope>
As you can see it does not work.

How to determine the vqmver in a vQmod xml script?

How can I determine the "correct" version of vqmver for the following vQmod xml script?
<?xml version="1.0" encoding="UTF-8"?>
<modification
xmlns="https://github.com/vqmod/vqmod"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/vqmod/vqmod https://raw.githubusercontent.com/vqmod/vqmod/master/vqmod.xsd"
>
<id>Replace 123 with ABC</id>
<version>1.0.0</version>
<vqmver>2.5.0</vqmver>
<author>qphoria</author>
<file name="relative/path/myfile.php">
<operation>
<search position="replace"><![CDATA[
$var = '123';
]]></search>
<add><![CDATA[
$var = 'ABC';
]]></add>
</operation>
</file>
</modification>
I have found some information here https://github.com/vqmod/vqmod/wiki/Scripting , but it doesn't explain in more details.

How do I search a node with namespaces defined in the same node

If ancestor nodes defines namespaces, I can use them:
> Nokogiri::XML(<<-XML
<?xml version='1.0' encoding='UTF-8'?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="bookid">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:creator opf:role="aut">John Doe</dc:creator>
</metadata>
</package>
XML
> xml.at_xpath("//dc:creator[#opf:role='aut']", xml.at_xpath("//xmlns:metadata").namespaces).text
=> "John Doe"
However, what shall I do with following XML?
> Nokogiri::XML(<<-XML
<?xml version='1.0' encoding='UTF-8'?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="bookid">
<metadata>
<dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf" opf:role="aut">John Doe</dc:creator>
</metadata>
</package>
XML
> xml.at_xpath("//dc:creator[#opf:role='aut']", xml.at_xpath("//xmlns:metadata").namespaces).text
Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: //dc:creator[#opf:role='aut']
I think xml.remove_namespaces! or literal namespace arguments for at_xpath is last resort.
To programmatically collect all the namespaces, use Document#collect_namespaces.
xml = Nokogiri::XML(xmldata)
ns = xml.collect_namespaces
puts xml.at('//dc:creator[#opf:role="aut"]', ns).text
Output:
John Doe

concat of multiple elements in xforms

I have the following data instance.
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
xmlns:exforms="http://www.exforms.org/exf/1-0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xhtml:head>
<xforms:instance id="instanceData">
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<fruits>
<fruit>
<fruit-name>Mango</fruit-name>
</fruit>
<fruit>
<fruit-name>Apple</fruit-name>
</fruit>
<fruit>
<fruit-name>Banana</fruit-name>
</fruit>
</fruits>
<all-fruits></all-fruits>
</form>
</xforms:instance>
</xhtml:head>
</xhtml:html>
i would like to have all the fruit names in all-fruits tag as below
<all-fruits>Mango Apple Banana</all-fruits>
Please suggest some way to achieve the same. It didn't work for me when tried with xxforms:iterate and concat.
The following does the trick:
<xforms:bind nodeset="all-fruits"
calculate="string-join(../fruits/fruit/fruit-name, ' ')"/>
And here is the full source so you can run it:
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
xmlns:exforms="http://www.exforms.org/exf/1-0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xforms="http://www.w3.org/2002/xforms">
<xhtml:head>
<xforms:model>
<xforms:instance id="instanceData">
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<fruits>
<fruit>
<fruit-name>Mango</fruit-name>
</fruit>
<fruit>
<fruit-name>Apple</fruit-name>
</fruit>
<fruit>
<fruit-name>Banana</fruit-name>
</fruit>
</fruits>
<all-fruits></all-fruits>
</form>
</xforms:instance>
<xforms:bind nodeset="all-fruits" calculate="string-join(../fruits/fruit/fruit-name, ' ')"/>
</xforms:model>
</xhtml:head>
<xhtml:body/>
</xhtml:html>

Resources