dbms_xmldom - How to get the <?xml tag - oracle

I am trying to get the line <?xml ....?> at the start of the XML document using the PL/SQL Package dbms_xmldom. Here is the code so far
declare
l_dom dbms_xmldom.DOMDocument;
l_clob clob;
l_node dbms_xmldom.DOMNode;
begin
l_dom := dbms_xmldom.newDomDocument;
l_node := dbms_xmldom.makeNode(l_dom);
l_node := dbms_xmldom.appendChild(l_node,
dbms_xmldom.makeNode(
dbms_xmldom.createElement(l_dom, 'root')
)
);
dbms_lob.createtemporary(l_clob, true);
dbms_xmldom.writeToClob(l_dom, l_clob);
dbms_output.put_line(l_clob);
end;
The output is:
<root/>
Expect:
<?xml version="1.0" encoding="UTF-8"?>
<root/>
Any pointers on how to do this would get great.

Just for the record - here is what you need to add
dbms_xmldom.setVersion(l_dom, '1.0" encoding="UTF-8');
after creating the document

The prolog is usually added automatically by XML serialization, so you shouldn't need to add it yourself, but if you want to you can with XMLRoot.
Your method for generating XML is quite inefficient. You should be looking at XMLElement, XMLForest, XMLAgg etc.
Here's a simple root and child example, with prolog in one line of code.
select XMLRoot(XMLElement("root", XMLElement("child", 12)), version '1.0') from dual
<?xml version="1.0"?>
<root>
<child>12</child>
</root>

Related

Inno Setup to modify key values in app.config file while running setup.exe

I need to change the values of some keys in app.config file. I'm planning to use Inno Setup for this task.
I have found excellent tips of using XML parser and xpath selectors in this kind of tasks. However, I don't know what path to use to point to the key & value I want to change.
My app.config looks approximately like this:
<configuration>
<runtime>
</runtime>
<appSettings>
<add key="DefaultUrl" value="http://localhost/Some_application"/>
</appSettings>
</configuration>
So, I want to access the key "DefaultUrl" and change it's "value". How to point there?
$x("//configuration/appSettings[#key='DefaultUrl']")
doesn't seem to be correct since it returns nothing.
EDIT after Mirtheil's comment:
To change the key values I use this procedure:
procedure SaveAttributeValueToXML(const AFileName, APath, AAttribute,
AValue: string);
var
XMLNode: Variant;
XMLDocument: Variant;
begin
XMLDocument := CreateOleObject('Msxml2.DOMDocument.6.0');
try
XMLDocument.async := False;
XMLDocument.load(AFileName);
if (XMLDocument.parseError.errorCode <> 0) then
MsgBox('The XML file could not be parsed. ' +
XMLDocument.parseError.reason, mbError, MB_OK)
else
begin
XMLDocument.setProperty('SelectionLanguage', 'XPath');
XMLNode := XMLDocument.selectSingleNode(APath);
XMLNode.setAttribute(AAttribute, AValue);
XMLDocument.save(AFileName);
end;
except
MsgBox('An error occured!' + #13#10 + GetExceptionMessage,
mbError, MB_OK);
end;
end;
I call it
SaveAttributeValueToXML(Some_Application.exe.config', '//configuration/appSettings[#key=''DefaultUrl'']', 'value', 'https://Server_Name/Other_Application');
This call generates an exception on line
XMLNode.setAttribute(AAttribute, AValue);
Exception message: "Variant is null, cannot invoke"
EDIT 2:
I found the answer. Calling
SaveAttributeValueToXML(Some_Application.exe.config', '//configuration/appSettings/add[#key=''DefaultUrl'']', 'value', 'https://Server_Name/Other_Application');
changes the value of key "DefaultUrl".
I found the answer.
$x("//configuration/appSettings/add[#key='DefaultUrl']")
returns the node I want.

Extract data from XMLTYPE variable

I have an XML below from which I am trying to extract the error tag data:
<ns1:updateStatusResponse xmlns:ns1="http://www.example.com/webservices">
<return href="#ID1"/>
</ns1:updateStatusResponse>
<ns3:OrderStatusUpdateResponse xmlns:ns3="http://www.example.com/com.example.com.ful.mod" id="ID1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:OrderStatusUpdateResponse">
<status xsi:type="xsd:string">ERROR</status>
<statusDetail xsi:type="xsd:string">Error occured when updating status for example</statusDetail>
</ns3:OrderStatusUpdateResponse>
I am using a logic like this, where resp is XMLTYPE and v_resp is VARCHAR2
v_resp := resp.EXTRACT (
'ns3:OrderStatusUpdateResponse/status/text()',
'xmlns:ns3="http://http://www.example.com/com.example.com.ful.mod" id="ID1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:OrderStatusUpdateResponse').getstringval ();
Whenever I run this in my code, I get an exception but no message.
Can someone please help me resolve this?

Oracle error when parsing XML data: LPX-00663

Im getting below error, can anyone please help me resolve it.
the ORA-31011: the XML parsing failed The  the ORA-19202: the Error
Occurred in the XML processing support  The LPX-00663:. VM
String-Stack overflow
I could see solution as Increase the size bed of the VM StringStack in XmlXslVMCreate ()  in some websites but no steps given on how to do it.
From Oracle Documentation.
PL/SQL package DBMS_XSLPROCESSOR provides a convenient and efficient
way of applying a single style sheet to multiple documents. The
performance of this package is better than that of method transform(),
because the style sheet is parsed only once.
I had the same problem. Workaround was. Something like this.
DECLARE
v_out_clob CLOB;
v_in_xml XMLTYPE;
v_in_xsl XMLTYPE;
ctx_xslproc dbms_xslprocessor.processor;
v_in_xsl_dd dbms_xmldom.DOMDocument;
v_in_xml_dd dbms_xmldom.DOMDocument;
v_styleshet dbms_xslprocessor.stylesheet;
BEGIN
v_in_xml := new xmltype('<?xml version="1.0" encoding="ISO-8859-1"?><document></document>');
v_in_xsl := new xmltype('<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
</head>
<body>
<br />
</body>
</html>
</xsl:template>
</xsl:stylesheet>');
ctx_xslproc := dbms_xslprocessor.newProcessor;
v_in_xsl_dd := dbms_xmldom.newDOMDocument(v_in_xsl);
v_in_xml_dd := dbms_xmldom.newDOMDocument(v_in_xml);
v_styleshet := dbms_xslprocessor.newStyleSheet(v_in_xsl_dd, NULL);
dbms_lob.createtemporary(v_out_clob,FALSE);
dbms_xslprocessor.processXSL(ctx_xslproc,v_styleshet,v_in_xml_dd,v_out_clob);
dbms_xmldom.freeDocument(v_in_xsl_dd);
dbms_xmldom.freeDocument(v_in_xml_dd);
dbms_xslprocessor.freeProcessor(ctx_xslproc);
dbms_output.put_line(v_out_clob);
END;

I want to omit specifying default namespace using libxml-ruby

I have questions about libxml-ruby.
There is a xml file "sample.xml".
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://***" xmlns:r="http://???">
<sheetData>
<row><v>1</v></row>
</sheetData>
</worksheet>
I want to deal with nodes without specifying default namespace like below.
xml = XML::Document.file('sample.xml')
sheet_data = xml.find_first('sheetData')
Of course, I can do it like below.
NS = {
main: 'http://***',
r: 'http://???',
}
sheet_data = xml.find_first('main:sheetData', NS)
But I want to omit string of default namespace.
I tried some properties and methods belongs to XML::Namespace[s], but not effected.
And one more problem when I save a xml file.
ns = XML::Namespace.new(xml.root, 'main', 'http://***')
row = XML::Node.new('row', nil, ns)
sheet_data << row
xml.save("sample.xml")
Published like below.
<row><v>1</v></row>
<main:row/>
I want that it's omitted string of "main:".
So I do this, but it's really ugly.
open('sample.xml', 'wb') do |f|
f.write(xml.to_s.gsub(/(<\/?)main:/, '\1'))
end
Do you have any good idea?

Replace all occurrences except the first in Ruby. The regular expression spans multiple lines

I am trying to down my last 3200 tweets in groups of 200(in multiple pages) using restclient gem.
In the process, I end up adding the following lines multiple times to my file:
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
To get this right(as the XML parsing goes for a toss), after downloading the file, I want to replace all occurrences of the above string except the first.
I am trying the following:
tweets_page = RestClient.get("#{GET_STATUSES_URL}&page=#{page_number}")
message = <<-MSG
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
MSG
unless page_number == 1
tweets_page.gsub!(message,"")
end
What is wrong in the above? Is there a better way to do the same?
I believe it would be faster to download the whole bunch at once and split the body of your response by message and add it for the first entry.
Something like this, can't try it out so consider this just as an idea.
tweets_page = RestClient.get("#{GET_STATUSES_URL}").body
tweets = tweets_page.split(message)
tweets_page = tweets[0]+message+tweets[1..-1]
You could easily break them up in groups of 200 like that also
If you want to do it with a gsub on the whole text you could use the following
tweets_page = <<-MSG
first
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
second
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
rest
MSG
message = <<-MSG
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
MSG
new_str = tweets_page.gsub message do |match|
if defined? #first
""
else
#first = true
message
end
end
p new_str
gives
type=\"array\">\nrest\n"
"first\n</statuses>\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<statuses type=\"array\">\nsecond\nrest\n"

Resources