Using XPATH to target nodes by partial name

104 views
Skip to first unread message

Robert Mark Bram

unread,
Oct 15, 2021, 1:52:51 AM10/15/21
to Smooks Users
I am exploring how to use Smooks and XPath expressions.

I am experimenting with java-to-xml with the following resource config:

<smooks-resource-list xmlns="https://www.smooks.org/xsd/smooks-2.0.xsd">
<resource-config selector="//*[contains(name(), 'org.smooks.examples.java2xml.model.Order')]">
<resource>org.smooks.examples.java2xml.EchoMessageVisitor</resource>
<param name="new-element-name">order</param>
</resource-config>

<resource-config selector="org.smooks.examples.java2xml.model.Order">
<resource>org.smooks.examples.java2xml.EchoMessageVisitor</resource>
<param name="new-element-name">order-new</param>
</resource-config>
</smooks-resource-list>


And a fairly simple transformer:

package org.smooks.examples.java2xml;

import org.smooks.api.ExecutionContext;
import org.smooks.api.resource.visitor.dom.DOMElementVisitor;
import org.smooks.support.DomUtils;
import org.w3c.dom.Element;

import javax.inject.Inject;
import javax.inject.Named;

public class EchoMessageVisitor implements DOMElementVisitor {

@Inject
@Named("new-element-name")
private String newElementName;

@Override
public void visitAfter(final Element element, final ExecutionContext executionContext) {
System.out.println("Rename " + element.getLocalName() + "to " + newElementName);
DomUtils.renameElement(element, newElementName, true, false);
}

@Override
public void visitBefore(final Element element, final ExecutionContext executionContext) {
}
}


I am having trouble working out how (or if) I can apply the more complicated XPATH expressions. In the example above, only the simple selector  is working (selector="org.smooks.examples.java2xml.model.Order"). Any idea how to use XPATH like this?

Rob
:)

Claude

unread,
Oct 16, 2021, 11:26:17 AM10/16/21
to Smooks Users
Greetings Rob,

Smooks implements a subset of XPath. The docs describe what's more or less what's supported. Coincidentally, I had started incorporating more support for XPath into Smooks but progress slowed down. As a side node, I've observed that you're running Smooks 2 but implementing DOMElementVisitor. Although this interface, and more generally DOM filtering, is still supported in Smooks 2, we recommend you implement org.smooks.api.resource.visitor.sax.ng.ElementVisitor since ElementVisitor unifies the legacy DOM API and the obsolete SAX API.

Claude 

Robert Mark Bram

unread,
Oct 16, 2021, 11:12:56 PM10/16/21
to Smooks Users
Thanks Claude,

> Smooks implements a subset of XPath. The docs describe what's more or less what's supported.

OK, so I cannot call any xpath function. 

> Although this interface, and more generally DOM filtering, is still supported in Smooks 2, we recommend you implement org.smooks.api.resource.visitor.sax.ng.ElementVisitor since ElementVisitor unifies the legacy DOM API and the obsolete SAX API.

That's great - I will stick to ElementVisitor then.

Rob
:)

Robert Mark Bram

unread,
Oct 16, 2021, 11:59:27 PM10/16/21
to Smooks Users
When using ElementVisitor (or  AfterVisitor), does that make DomUtils obsolete? 


package org.smooks.examples.java2xml;

import org.smooks.api.ExecutionContext;
import org.smooks.api.resource.visitor.sax.ng.AfterVisitor;

import org.smooks.support.DomUtils;
import org.w3c.dom.Element;

import javax.inject.Inject;
import javax.inject.Named;

public class EchoMessageVisitor implements AfterVisitor {


  @Inject
  @Named("new-element-name")
  private String newElementName;

  @Override
  public void visitAfter(final Element element, final ExecutionContext executionContext) {
    System.out.println("Rename " + element.getLocalName() + " to " + newElementName);
    DomUtils.renameElement(element, newElementName, true, false);
  }
}

This code now throws an exception, and I note there are no examples on v2 doc page showing DomUtils.

Exception in thread "main" org.smooks.api.SmooksException: Failed to filter source
at org.smooks.engine.delivery.sax.ng.SaxNgFilter.doFilter(SaxNgFilter.java:122)
at org.smooks.engine.delivery.sax.ng.SaxNgFilter.doFilter(SaxNgFilter.java:94)
at org.smooks.Smooks._filter(Smooks.java:547)
at org.smooks.Smooks.filterSource(Smooks.java:505)
at org.smooks.examples.java2xml.Main.runSmooksTransform(Main.java:81)
at org.smooks.examples.java2xml.Main.main(Main.java:101)
Caused by: java.lang.NullPointerException: Cannot invoke "org.w3c.dom.Node.getUserData(String)" because "node" is null
...

Claude

unread,
Nov 15, 2021, 12:51:22 PM11/15/21
to Smooks Users
Yes, DomUtils is meant for the legacy DOM API though it's not obsolete. I had provided an example a while back showing how to rename XML tags with the new pipeline feature.

Claude
Reply all
Reply to author
Forward
0 new messages