Punctually access specific nodes of an XML document
Hello!
I have the following XML document obtained through a string:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MainDocument xmlns="urn:hl7-org:v3">
<realmCode code="IT"/>
<title>kjbkjkjbkjb</title>
<effectiveTime value="20090905150716"/>
[.....other tags.....]
<versionNumber value="1"/>
<component>
<body>mhvjhjkvhj</body>
<component>
<section>content</section>
<ID>5</ID>
<title>Certificato</title>
<text/>
<entry>
<Id>5</Id>
[...other tags...]
</entry>
<entry>
<Id>6</Id>
[...other tags...]
</entry>
</component>
</component>
</ClinicalDocument>
I would like to have a way to obtain only the content of the <entry> tags (which can be multiple) without having to scan the whole xml document, since it would be inefficient because of its length. I would like to have an outcome similar to the one coming from EvaluateExpression() but, from my trials and examples found on the internet, it seems that this function can be used only when the tag contains just one value. Does anybody have any idea which might help?
Thank you in advance!
Comments
To punctually access specific nodes in an XML document, such as retrieving only <entry> tags, you can use the following approaches with InterSystems tools:
Using XPath: You can leverage the
%XML.XPATH.Documentclass to evaluate an XPath expression that targets the<entry>tags. For example:set status = ##class(%XML.XPATH.Document).CreateFromStream(stream, .mydoc) set status = mydoc.EvaluateExpression("//entry", "1", .myresults)After evaluating the expression, iterate over
myresultsto retrieve each<entry>element. Here,"//entry"directly fetches all<entry>elements in the document [1][2].Detailed Node Inspection Using
%XML.TextReader: If you wish to parse the document node by node:
Using %XML.XPATH.Document can directly fetch elements specified by an XPath expression and is more efficient when targeting specific elements like <entry> tags. For navigating documents manually, %XML.TextReader provides granular control node-by-node.
Sources:
Solution 1 is not working. Even though I get an element saved in myresults, if I try to access its content using myresults.GetAt(1).Value I get as the returned value the number 1
Class dc.test [ Abstract ]
{
ClassMethod Test()
{
#dim ex As %Exception.AbstractException
#dim xDataStream As %Stream.Object
#dim mydoc As %XML.XPATH.Document
try{
set xDataStream=##class(%Dictionary.CompiledXData).IDKEYOpen(..%ClassName(1),"ClinicalDocXData").Data
$$$ThrowOnError(##class(%XML.XPATH.Document).CreateFromStream(xDataStream, .mydoc,,,,,"s urn:hl7-org:v3"))
$$$ThrowOnError(mydoc.EvaluateExpression("//s:entry/s:Id", "text()", .tRes))
for i =1:1:tRes.Count() {
write tRes.GetAt(i).Value,!
}
}catch(ex) {
write "Error ", ex.DisplayString(),!
}
}
XData ClinicalDocXData
{
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MainDocument xmlns="urn:hl7-org:v3">
<realmCode code="IT"/>
<title>kjbkjkjbkjb</title>
<effectiveTime value="20090905150716"/>
<versionNumber value="1"/>
<component>
<body>mhvjhjkvhj</body>
<component>
<section>content</section>
<ID>5</ID>
<title>Certificato</title>
<text/>
<entry>
<Id>5</Id>
</entry>
<entry>
<Id>6</Id>
</entry>
</component>
</component>
</MainDocument>
}
}Result:USER>do ##class(dc.test).Test()5 6
Hello!
Thanks for your reply. At the end, I implemented a solution very similar to yours. Apparently, there is no way to obtain something that is not a text, an occurrence count or an attribute like I hoped.
Late suggestion:
if you interpret your <entry> as a piece separator in your XML string, you may apply this trick
;; asssuming your input is in xmltext;; get the 4th entryset entry4=$piece($piece(xmltest,"<entry>",4+1),"</entry>")
;;-------^---------------------------------^Hi!
Thank you for the suggestion but I decided to use the XPATH implementation.
Clear ! That's what XPATH was meant for