Fwd: Saxon-HE update text node without using XQuery Update

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Fwd: Saxon-HE update text node without using XQuery Update

Meindert Oldenburger
Are the following actions possible to implement, Saxon-HE, with API methods?:
- update the XdmNode of type text with another text string;
- add a XdmNode of type text;
- delete a XdmNode of type text.


------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Saxon-HE update text node without using XQuery Update

Michael Kay
It depends on the tree model you are using. If you want to do in-situ update, I would recommend using a tree model that's designed for it, like JDOM2 or XOM. The Saxon "linked tree" supports in-situ update, but it's not designed to be used directly because the methods don't do all the integrity checks needed, they rely on higher levels of software for that.

Given an XdmNode, you then dive down to the underlying NodeInfo and from there to the underlying JDOM2 or XOM node, and manipulate it using its native APIs.

If you're doing this from within an XSLT extension function, it's at your own risk, because the order of processing is not always predictable.

Michael Kay
Saxonica

> On 19 Dec 2015, at 08:43, Meindert Oldenburger <[hidden email]> wrote:
>
> Are the following actions possible to implement, Saxon-HE, with API methods?:
> - update the XdmNode of type text with another text string;
> - add a XdmNode of type text;
> - delete a XdmNode of type text.
>
> ------------------------------------------------------------------------------
> _______________________________________________
> saxon-help mailing list archived at http://saxon.markmail.org/
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/saxon-help



------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Saxon-HE update text node without using XQuery Update

Meindert Oldenburger
Thanks Michael for you answer. I'm using Saxon from windows .NET and parse the XML with help of a DocumentBuider created by the processor. I have no clue what the underlying model is and how I can change it. I need to make simple changes of text nodes and have a Saxon implementation at the moment. I only use XPath and XQuery so no XSLT.


2015-12-19 11:52 GMT+01:00 Michael Kay <[hidden email]>:
It depends on the tree model you are using. If you want to do in-situ update, I would recommend using a tree model that's designed for it, like JDOM2 or XOM. The Saxon "linked tree" supports in-situ update, but it's not designed to be used directly because the methods don't do all the integrity checks needed, they rely on higher levels of software for that.

Given an XdmNode, you then dive down to the underlying NodeInfo and from there to the underlying JDOM2 or XOM node, and manipulate it using its native APIs.

If you're doing this from within an XSLT extension function, it's at your own risk, because the order of processing is not always predictable.

Michael Kay
Saxonica

> On 19 Dec 2015, at 08:43, Meindert Oldenburger <[hidden email]> wrote:
>
> Are the following actions possible to implement, Saxon-HE, with API methods?:
> - update the XdmNode of type text with another text string;
> - add a XdmNode of type text;
> - delete a XdmNode of type text.
>
> ------------------------------------------------------------------------------
> _______________________________________________
> saxon-help mailing list archived at http://saxon.markmail.org/
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/saxon-help



------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help


------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Saxon-HE update text node without using XQuery Update

Michael Kay
OK, on .NET you don't have the wide range of third party tree models that you have on the Java platform: the only option is really the Microsoft DOM. 

Create an XmlDocument object using the Microsoft parser, and then use DocumentBuilder.wrap(XmlDocument doc) to wrap this as a Saxon XdmNode. You can then do XPath processing on this in the same way as any other XdmNode. When you want to do an update, use XdmNode.getUnderlyingXmlNode to get back to the DOM node, and then you can use the updating methods supplied by the DOM.

Michael Kay
Saxonica

On 19 Dec 2015, at 11:17, Meindert Oldenburger <[hidden email]> wrote:

Thanks Michael for you answer. I'm using Saxon from windows .NET and parse the XML with help of a DocumentBuider created by the processor. I have no clue what the underlying model is and how I can change it. I need to make simple changes of text nodes and have a Saxon implementation at the moment. I only use XPath and XQuery so no XSLT.


2015-12-19 11:52 GMT+01:00 Michael Kay <[hidden email]>:
It depends on the tree model you are using. If you want to do in-situ update, I would recommend using a tree model that's designed for it, like JDOM2 or XOM. The Saxon "linked tree" supports in-situ update, but it's not designed to be used directly because the methods don't do all the integrity checks needed, they rely on higher levels of software for that.

Given an XdmNode, you then dive down to the underlying NodeInfo and from there to the underlying JDOM2 or XOM node, and manipulate it using its native APIs.

If you're doing this from within an XSLT extension function, it's at your own risk, because the order of processing is not always predictable.

Michael Kay
Saxonica

> On 19 Dec 2015, at 08:43, Meindert Oldenburger <[hidden email]> wrote:
>
> Are the following actions possible to implement, Saxon-HE, with API methods?:
> - update the XdmNode of type text with another text string;
> - add a XdmNode of type text;
> - delete a XdmNode of type text.
>
> ------------------------------------------------------------------------------
> _______________________________________________
> saxon-help mailing list archived at http://saxon.markmail.org/
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/saxon-help



------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help

------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help


------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Saxon-HE update text node without using XQuery Update

Martin Honnen-2
Michael Kay wrote:

> Create an XmlDocument object using the Microsoft parser, and then use
> DocumentBuilder.wrap(XmlDocument doc) to wrap this as a Saxon XdmNode.
> You can then do XPath processing on this in the same way as any other
> XdmNode. When you want to do an update, use XdmNode.getUnderlyingXmlNode
> to get back to the DOM node, and then you can use the updating methods
> supplied by the DOM.

Here is an example:

             Processor proc = new Processor();

             XmlDocument doc1 = new XmlDocument();
 
doc1.LoadXml("<root><item>foo</item><item>bar</item><item>foobar</item></root>");

             XdmNode input1 = proc.NewDocumentBuilder().Wrap(doc1);

             XPathCompiler comp = proc.NewXPathCompiler();

             XPathSelector selector = comp.Compile("root/item[matches(.,
'^foo')]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode item in selector.Evaluate())
             {
                 XmlNode itemNode = item.getUnderlyingXmlNode();
                 itemNode.InnerText = "whatever";
             }

             Console.WriteLine(input1.ToString());

             selector = comp.Compile("root/item/text()[contains(.,
'whatever')]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode text in selector.Evaluate())
             {
                 XmlNode textNode = text.getUnderlyingXmlNode();
                 textNode.ParentNode.RemoveChild(textNode);
             }

             Console.WriteLine(input1.ToString());

             selector = comp.Compile("root/item[not(node())]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode item in selector.Evaluate())
             {
                 XmlNode itemEl = item.getUnderlyingXmlNode();
                 itemEl.InnerText = DateTime.Now.ToString();
             }

             Console.WriteLine(input1.ToString());

Outputs

<root>
    <item>whatever</item>
    <item>bar</item>
    <item>whatever</item>
</root>

<root>
    <item/>
    <item>bar</item>
    <item/>
</root>

<root>
    <item>19.12.2015 15:16:38</item>
    <item>bar</item>
    <item>19.12.2015 15:16:38</item>
</root>



------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Saxon-HE update text node without using XQuery Update

Meindert Oldenburger

That is interesting. If I understand it, the xdmnode wrap is done dynamically? Zo do what I like with the xmlnode structuren and the xquery is working without reloading it?

Op 19 dec. 2015 15:20 schreef "Martin Honnen" <[hidden email]>:
Michael Kay wrote:

> Create an XmlDocument object using the Microsoft parser, and then use
> DocumentBuilder.wrap(XmlDocument doc) to wrap this as a Saxon XdmNode.
> You can then do XPath processing on this in the same way as any other
> XdmNode. When you want to do an update, use XdmNode.getUnderlyingXmlNode
> to get back to the DOM node, and then you can use the updating methods
> supplied by the DOM.

Here is an example:

             Processor proc = new Processor();

             XmlDocument doc1 = new XmlDocument();

doc1.LoadXml("<root><item>foo</item><item>bar</item><item>foobar</item></root>");

             XdmNode input1 = proc.NewDocumentBuilder().Wrap(doc1);

             XPathCompiler comp = proc.NewXPathCompiler();

             XPathSelector selector = comp.Compile("root/item[matches(.,
'^foo')]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode item in selector.Evaluate())
             {
                 XmlNode itemNode = item.getUnderlyingXmlNode();
                 itemNode.InnerText = "whatever";
             }

             Console.WriteLine(input1.ToString());

             selector = comp.Compile("root/item/text()[contains(.,
'whatever')]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode text in selector.Evaluate())
             {
                 XmlNode textNode = text.getUnderlyingXmlNode();
                 textNode.ParentNode.RemoveChild(textNode);
             }

             Console.WriteLine(input1.ToString());

             selector = comp.Compile("root/item[not(node())]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode item in selector.Evaluate())
             {
                 XmlNode itemEl = item.getUnderlyingXmlNode();
                 itemEl.InnerText = DateTime.Now.ToString();
             }

             Console.WriteLine(input1.ToString());

Outputs

<root>
    <item>whatever</item>
    <item>bar</item>
    <item>whatever</item>
</root>

<root>
    <item/>
    <item>bar</item>
    <item/>
</root>

<root>
    <item>19.12.2015 15:16:38</item>
    <item>bar</item>
    <item>19.12.2015 15:16:38</item>
</root>



------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help

------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Saxon-HE update text node without using XQuery Update

Michael Kay
Yes, the wrap() operation creates a "live link" so that changes to the XmlNode (the DOM node) affect the XdmNode wrapper. The XdmNode is effectively a pointer to the XmlNode. XPath/XQuery isn't designed to deal with mutable data so strange things can happen, e.g. if your attempt to delete the underlying node, but simple things like changing the text content will generally work.

Michael Kay
Saxonica

On 19 Dec 2015, at 14:37, Meindert Oldenburger <[hidden email]> wrote:

That is interesting. If I understand it, the xdmnode wrap is done dynamically? Zo do what I like with the xmlnode structuren and the xquery is working without reloading it?

Op 19 dec. 2015 15:20 schreef "Martin Honnen" <[hidden email]>:
Michael Kay wrote:

> Create an XmlDocument object using the Microsoft parser, and then use
> DocumentBuilder.wrap(XmlDocument doc) to wrap this as a Saxon XdmNode.
> You can then do XPath processing on this in the same way as any other
> XdmNode. When you want to do an update, use XdmNode.getUnderlyingXmlNode
> to get back to the DOM node, and then you can use the updating methods
> supplied by the DOM.

Here is an example:

             Processor proc = new Processor();

             XmlDocument doc1 = new XmlDocument();

doc1.LoadXml("<root><item>foo</item><item>bar</item><item>foobar</item></root>");

             XdmNode input1 = proc.NewDocumentBuilder().Wrap(doc1);

             XPathCompiler comp = proc.NewXPathCompiler();

             XPathSelector selector = comp.Compile("root/item[matches(.,
'^foo')]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode item in selector.Evaluate())
             {
                 XmlNode itemNode = item.getUnderlyingXmlNode();
                 itemNode.InnerText = "whatever";
             }

             Console.WriteLine(input1.ToString());

             selector = comp.Compile("root/item/text()[contains(.,
'whatever')]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode text in selector.Evaluate())
             {
                 XmlNode textNode = text.getUnderlyingXmlNode();
                 textNode.ParentNode.RemoveChild(textNode);
             }

             Console.WriteLine(input1.ToString());

             selector = comp.Compile("root/item[not(node())]").Load();
             selector.ContextItem = input1;

             foreach (XdmNode item in selector.Evaluate())
             {
                 XmlNode itemEl = item.getUnderlyingXmlNode();
                 itemEl.InnerText = DateTime.Now.ToString();
             }

             Console.WriteLine(input1.ToString());

Outputs

<root>
    <item>whatever</item>
    <item>bar</item>
    <item>whatever</item>
</root>

<root>
    <item/>
    <item>bar</item>
    <item/>
</root>

<root>
    <item>19.12.2015 15:16:38</item>
    <item>bar</item>
    <item>19.12.2015 15:16:38</item>
</root>



------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help
------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help


------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help