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/*");
Related
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
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.
I am using xslt filter for importing/exporting data from Calc worksheet. Is it possible to refer to a specific cell address ? For example, if we want to export data from cell B2, how do we refer to this cell address in export xslt ?
Without knowing much about Openoffice or their xslt filter function, I can tell you that you're probably going to need a fairly simple XPath to reference a specific Cell's data - I doubt it would be as simple as calling getCell('B2') unless they have provided you with some custom xslt functions (I'm assuming they've put you in a raw XSLT environment).
Anyway, I think this question may be more about XSLT and xpath, than it is about openoffice. With that in mind, I'm going to fashion my own sample xml and examples and hopefully that will be enough to get you started.
For an input xml that looks something like this:
<ooo_calc_export>
<ooo_sheet num="1" name="sheet1">
<ooo_row num="2">
<fisrtCell>Oh</firstCell>
<secondCell>Hai</secondCell>
<thirdCell>There</thirdCell>
</ooo_row>
<ooo_row num="3">
<fisrtCell>Oh</firstCell>
<secondCell>Hello</secondCell>
<thirdCell>Back!</thirdCell>
</ooo_row>
</ooo_sheet>
</ooo_calc_export>
An absolute XPath to access cell B2's data would look like this ooo_calc_export/ooo_sheet/ooo_row[#num='2']/secondCell/text()
But the above is an absolute path and in XSLT, we would often author relative xpaths as we are in the midst of processing a document. Imagine you're in a template which matches on the ooo_calc_export node and you wanted to store Cell B2's data in a variable for later use. Consider this example:
<xsl:template match="/ooo_calc_export">
<!-- a relative xpath does not being with a forward slash -->
<xsl:variable name="B2" select="ooo_sheet/ooo_row[#num='2']/secondCell/text()" />
</xsl:template>
Now lets imagine you wanted a template to match on the cell B2 node itself:
<xsl:template match="ooo_row[#num='2']/secondCell">
<!-- a relative xpath does not being with a forward slash -->
<xsl:variable name="B2_text" select="text()" />
</xsl:template>
This is a good tutorial on XSLT to get you started. Also, the W3 Schools references on XPath and XSLT aren't the worst.
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.
the xml has this format:
UDF Fields
Inline Portion - Child of multiple Nodes
<Activity>
<UDF>
<TypeObjectId>458</TypeObjectId>
<TextValue>MILS-Z.M1.01</TextValue>
</UDF>
Definition Portion - Child of top node
<UDFType>
<DataType>0</DataType>
<IsSecureCode>0</IsSecureCode>
<ObjectId>458</ObjectId>
<SubjectArea>0</SubjectArea>
<Title>Contract Package</Title>
</UDFType>
I need to find the parents of the UDF by going in through UDFType, looping a search for UDF and then listing the parents of the UDF. Any advice?
Use the xpath: //UDF/.. to match the parent nodes of all UDF elements. Or you could just do //*[UDF], which specifically matches any element that has a UDF child.