BaseX XQuery replace - replace

I have the following problem. I want to replace a value of an element in my xquery-file by using baseX as the database. The xquery code is as follows:
let $db := doc('update.xml')
replace value of node $db//elem with 'haha'
return <result> {$db//elem/text()} </result>
The xml document contains the following elements:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<check>
<ok>
<elem>test</elem>
<help></help>
</ok>
</check>
</root>
Everytime I want to execute this xquery an error like this is thrown:
Expecting 'where', 'order' or 'return' expression
so what should i do or change, to just replace the text "test" by "haha" in the element ?
If I use just this line of code it works, but I have to read out of URL-Parameter so I need more lines of code, except the "replace...." line!

let starts a flwor-expression which may not directly contain update statements. You will have to put a return between these two:
let $db := doc('update.xml')
return
replace value of node $db//elem with 'haha'
You will also be able to do arbitrary calculations, but make sure not to have any output returned by your query.
There is no way to use updating statements and return a result at the same time.

Related

Replace partial data in an element using xquery

I am trying to replace partial data of an element with empty string in xquery. I have ticket details xml and email to remove xml with me. Now i need to form an xquery which would modify the ticket details xml by removing the email ids that are there in the element EmailIdToDelete available in second xml from the element EmailId available in first xml and give me the expected output. The xquery version used is not latest. I guess it is very old. Need to check that.
Could someone please help me with this?
Ticket Details xml:
<TicketDetails>
<EmailInformation>
<EmailId>test1#aaa.com;test2#aaa.com;test3#aaa.com;test4#aaa.com;test5#aaa.com;test6#aaa.com;test7#aaa.com;test8#aaa.com</EmailId>
</EmailInformation>
</TicketDetails>
Email to remove xml:
<Details>
<EmailDetails>
<EmailIdToDelete>test2#aaa.com</EmailIdToDelete>
<EmailIdToDelete>test5#aaa.com</EmailIdToDelete>
<EmailIdToDelete>test8#aaa.com</EmailIdToDelete>
</EmailDetails>
</Details>
Expected output:
<TicketDetails>
<EmailInformation>
<EmailId>test1#aaa.com;test3#aaa.com;test4#aaa.com;test6#aaa.com;test7#aaa.com;</EmailId>
</EmailInformation>
</TicketDetails>
You could tokenize on ; and then simply compare and only select the values without a match in the second document:
<EmailId>{string-join(tokenize(TicketDetails/EmailInformation/EmailId, ';')[not(. = $remove/Details/EmailDetails/EmailIdToDelete)], ';')}</EmailId>
where $remove is the second document e.g. let $remove := doc('remove.xml') or an external parameter:
declare variable $remove as document-node() external := document {
<Details>
<EmailDetails>
<EmailIdToDelete>test2#example.com</EmailIdToDelete>
<EmailIdToDelete>test5#example.com</EmailIdToDelete>
<EmailIdToDelete>test8#example.com</EmailIdToDelete>
</EmailDetails>
</Details>
};
<TicketDetails>
<EmailInformation>
<EmailId>{string-join(tokenize(TicketDetails/EmailInformation/EmailId, ';')[not(. = $remove/Details/EmailDetails/EmailIdToDelete)], ';')}</EmailId>
</EmailInformation>
</TicketDetails>
https://xqueryfiddle.liberty-development.net/gWmuPs2

Issue with xslt processing

I get the following error after my xslt has been processed:
There are 1 schema validation error(s):
1. Error Msg:The element 'BusinessObjectList' has incomplete content. List of possible elements expected: 'BusinessObject'. Line Number: 1, Line Position: 40, Severity:Error
I am trying to troubleshoot this issue and just require some clarifications. From my understanding of this error, there is a missing element called BusinessObject. So, I am not too sure if i have to incorporate this missing element or replace the existing element with this? another question too is, how to refer to Line 1, Line Position 40 in my xslt file?
Below is how the beginning of the xslt looks like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:template match="/">
<BusinessObjectList SchemaVersion="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="HierarchicalObjects-1.0.xsd">
You haven't told us how you are running the transformation, but it seems to be configured so that on completion the result document is validated against the schema at HierarchicalObjects-1.0.xsd. Presumably that schema says that the BusinessObjectList must contain at least N BusinessObject elements (perhaps N is 1, we don't know), and your transformation output includes less than N.
You either need to produce output that conforms to the schema, or you need to change the way you are processing to avoid the validation step.
The line/column number probably refers to a line/column in the result document, not in the stylesheet.

How to check for blank elements in XML?

Is there a regex to check for empty elements for the XML below? So I want to check whether or not everything below the <ClientRequest> tags are populated or not?
<Response xmlns="http://Test/Types">
<ClientRequest>
<Name>TEST</Name>
<Id><222/Id>
<Parameters>
<SID>123456</SID>
</RequestParams>
<StartDate>2017-10-13T23:00:01.000+01:00</StartDate>
<EndDate>2017-10-14T22:59:59.000+01:00</EndDate>
<URL></URL>
</ClientRequest>
<Install/>
<Types/>
<LR/>
<Package/>
<Services/>
<Issues/>
<Complaints/>
</Response>
Use an XML parser or XPath, not regex, to check or parse XML.
This XPath,
//*[not(text()) and not(*)]
will select all elements that have no text or element children.
This XPath,
//*[not(node())]
will select all empty elements (also disallowing comment and PI children).
Note that your XML is not well-formed. Here it is with corrections:
<Response xmlns="http://Test/Types">
<ClientRequest>
<Name>TEST</Name>
<Id>222</Id>
<Parameters>
<SID>123456</SID>
</Parameters>
<StartDate>2017-10-13T23:00:01.000+01:00</StartDate>
<EndDate>2017-10-14T22:59:59.000+01:00</EndDate>
<URL></URL>
</ClientRequest>
<Install/>
<Types/>
<LR/>
<Package/>
<Services/>
<Issues/>
<Complaints/>
</Response>
Note also that you could wrap either of the above XPaths in boolean() or count() to return an indicator or count of the presence of such populated elements.

XSLT Filter on property

I am needing a little help with filtering my xml based on a property
I have the XML in the following format:
<?xml version="1.0" encoding="utf-8" ?>
<root id="-1">
<LandingPage id="1067" parentID="1050" level="2"
writerID="0" creatorID="0" nodeType="1066" template="1073"
sortOrder="0" createDate="2013-02-04T14:29:39"
updateDate="2013-02-07T11:08:27" nodeName="About"
urlName="about" writerName="Pete" creatorName="Pete"
path="-1,1050,1067" isDoc="">
<hideInNavigation>0</hideInNavigation>
</LandingPage>
</root>
What I need to do is filter these elements where hideInNavigation = 0
I have tried the following:
[#isDoc and #hideInNavigation ='0']
(I need the #isDoc attribute too) but realised this would only work if hideInNavigation was an attribute of the LandingPage tag so I tried
value['hideInNavigation'='0']
but this didn't seem to do anything either. After much searching for the answer, I haven't come up with anything so was wondering if it is possible
Supposing the current context was the <root> element, you could select the LandingPages with hideInNavigation = 0 with:
LandingPage[hideInNavigation = '0']
If you would share your XSLT, I van give you more specific guidance on how to amend it for this particular case.
And was the #isDoc test in your first example something you wanted? Do you want to filter LandingPages that have an isDoc attribute and a hideInNavigation value of 0?
'hideInNavigation'='0' compares the two strings 'hideInNavigation' and '0', which are guaranteed to be different.
In the context of root, LandingPage[hideInNavigation=0] would match the LandingPage element in your example.
This XPath return all LandingPage with isDoc attribute empty and hideInNavigation element content is '0'
//LandingPage[#isDoc="" and hideInNavigation='0']

How do acquire a xml string for a child using msxml4?

Using MSXML4, I am creating and saving an xml file:
MSXML2::IXMLDOMDocument2Ptr m_pXmlDoc;
//add some elements with data
SaveToDisk(static_cast<std::string>(m_pXmlDoc->xml));
I now need to acquire a substring from m_pXmlDoc->xml and save it. For example, if the full xml is:
<data>
<child1>
<A>data</A>
<One>data</One>
<B>data</B>
</child1>
</data>
I want to store this substring instead:
<A>data</A>
<One>data</One>
<B>data</B>
How do I get this substring using MXML4?
Use XPath queries. See the MSDN documentaion for querying nodes. Basically you need to call the selectNodes API with the appropriate XPath expression that matches the part of the DOM you are interested in.
// Query a node-set.
MSXML4::IXMLDOMNodeListPtr pnl = pXMLDom->selectNodes(L"//child/*");