I'm trying to use XPath in my Web Application with Saxon 9.7.0-14 EE and xmlbeans-2.6.0 / xmlbeans-xpath-2.6.0
Movement mov = (Movement) XPathUtils.executeQueryNoResultNull(message.getPayload(), "//trx:Movement [#tipo='RESTO']");
with
public static XmlObject executeQueryNoResultNull(XmlObject source, String query) {
XmlObject[] results = source.selectPath(DECLARE_NS + "$this" + query);
if (results.length == 0) {
return null;
} else {
return results[0];
}
}
and I have this error
java.lang.RuntimeException: Trying XBeans path engine... Trying XQRL... Trying XDK... Trying delegated path engine... FAILED on declare namespace trx='http://www.test.com/xxx/xx/trx';$this//trx:Movement[#tipo='RESTO']
at org.apache.xmlbeans.impl.store.Path.getCompiledPath(Path.java:185)
at org.apache.xmlbeans.impl.store.Path.getCompiledPath(Path.java:136)
at org.apache.xmlbeans.impl.store.Cursor._selectPath(Cursor.java:902)
at org.apache.xmlbeans.impl.store.Cursor.selectPath(Cursor.java:2634)
at org.apache.xmlbeans.impl.values.XmlObjectBase.selectPath(XmlObjectBase.java:476)
at org.apache.xmlbeans.impl.values.XmlObjectBase.selectPath(XmlObjectBase.java:460)
Is the problem XMLBeans ? Can I use only Saxon and remove XMLBeans ?
Here my module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="app-common">
<resources>
<resource-root path="jsr173_1.0_api.jar"/>
<resource-root path="resolver.jar"/>
<resource-root path="xbean_xpath.jar"/>
<resource-root path="saxon9ee.jar"/>
<resource-root path="saxon9-dom.jar"/>
<resource-root path="xmlbeans-2.6.0.jar"/>
With XMLBeans version 3.1.0, the most recent version of SaxonHE that I have used successfully is 9.2.1-5. Anything at version 9.3 and above triggers the error that you have seen, i.e. a failed attempt to find an XPath engine that can cope with a query with predicates. The XMLBeans docs explain why the query works without the predicate:
By default, XMLBeans supports only very simple XPath expressions. To
execute complex expressions — such as those with predicates, function
calls, and the like — you will need xbean_xpath.jar and the Saxon jars
(see below) on your class path.
With XMLBeans 3.x, you don't need to include xbean_xpath.jar (the classes are included in xmlbeans-3.1.0.jar), although the documentation has not yet been updated to reflect this.
I'm no expert on XMLBeans, but I wonder if the problem is that the "XPath" expression in question
declare namespace trx='http://www.test.com/xxx/xx/trx';$this//trx:Movement[#tipo='RESTO']
is not true XPath (because of the 'declare namespace') and therefore doesn't work with a third-party XPath engine?
Related
I need to export a solution from PowerApps (model driven), version 9.2
and import it to CRM, version 9.1.
I have an error because of this version. How can I do this?
You need to export the solution for a previous target version.
In .NET/C# you can do this using the ExportSolutionRequest:
public string ExportSolution(string solutionName, bool asManaged)
{
var request = new ExportSolutionRequest
{
SolutionName = solutionName,
Managed = asManaged,
TargetVersion = "9.1"
};
var response = _service.Execute(request) as ExportSolutionResponse;
string solutionZipPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
File.WriteAllBytes(solutionZipPath, response.ExportSolutionFile);
return solutionZipPath;
}
In the example above _service is of type IOrganizationService.
Another solution would involve a tweak:
Export the solution.
Extract the solution zip.
Open the solution.xml manifest in a text editor.
In the root ImportExportXml element change the value of attribute SolutionPackageVersion into the desired version.
Save your changes.
Zip the solution.
Import the modified solution in the target environment.
<?xml version="1.0" encoding="utf-8"?>
<ImportExportXml version="9.2.21082.140" SolutionPackageVersion="9.2" languagecode="1033" generatedBy="CrmLive" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SolutionManifest>
...
</SolutionManifest>
</ImportExportXml>
Last approach does not guarantee the solution can be imported without issues as it can contain features not supported by a previous version. However, sometimes it is possible to remove these features by hand.
I am a beginner with Drools and Maven and I am facing a problem to load rules with KieScanner.
The aim of the project is to be able to dynamically load rules in a permanent KieSession. I wonder if it is possible to manage rules with the KieFileSystem (not sure it is possible without a dispose of the session and starting another one leading to the lack of the previous inserted facts), but the good way is to use KieScanner.
It seems this requires the creation of a Jar containing the rules and having a Maven ID (ReleaseId), but I could not find detailed documentation about creation of these Jar files.
Which files shall be included in such a Jar ? DRL files, Pom.xml and manifest.mf ?
Where can this Jar file be added ? According to documentation it should not be added in the classpath when the detection of new issues of that file is necessary : "once a module is on the classpath, no other version may be loaded dynamically".
Is a Maven command needed ?
Can someone give me information on those points or give me a link where creation and deployment of such a Jar and its management in a KieScanner is described ? Thanks a lot.
Here is an example of a stateless kiesession using a kjar from a maven repository (code is in scala, but i am sure you'll get the idea of you primarily program in Java)
private val services = KieServices.Factory.get
private val releaseId = services.newReleaseId("com.piedpiper", "demo", "[1.0,2)")
private val kieContainer = services.newKieContainer(releaseId)
val kScanner = services.newKieScanner(kieContainer)
kScanner.start(2000L)
val kieSession = kieContainer.newStatelessKieSession("SimpleSession")
#tailrec
def check() {
val (aName, aAge) = scala.io.StdIn.readf2("{0} {1,number}")
val applicant = Applicant(name = aName.asInstanceOf[String], age = aAge.asInstanceOf[Long].toInt, pass = false)
kieSession.execute(applicant)
println(s"valid is ${applicant.pass}")
check()
}
check()
This looks for a kjar using maven with the gav com.piedpiper:demo:[1.0,2) (iow any version from 1.0 to 2 (non-inclusive). It checks every two seconds if a new version within that range is available.
The kjar contains the knowledge resources, the kmodule.xml etc (a proper kjar with the compiled rules using the kie-maven-plugin plugin-extension ). In this case it also contains the fact model (i would normally separate that out in a different maven artefact.)
The rule used in the example above is
rule "Is of valid age"
when
$a : Applicant( age > 13, pass==false )
then
modify($a){
pass = true
}
end
When changing the rule to for example > 15, it takes 2 seconds to become operational.
Here is an example to use MemoryFileSystem to create KJar and use it to create KieContainer
Input:
releaseId - Could be TimeStamp and UUID
ruleContentList - DRL file stringified list
public static final String IN_MEM_RULE_PATH = "src/main/resources/";
public static final String RULE_RESOURCE_TYPE = "drl";
public static byte[] createKJar(ReleaseId releaseId, List<String> ruleContentList) {
KieServices kieServices = KieServiceProvider.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.generateAndWritePomXML(releaseId);
ruleContentList.forEach(drl -> kfs.write(IN_MEM_RULE_PATH + drl.hashCode() + "." + RULE_RESOURCE_TYPE, drl));
KieBuilder kb = kieServices.newKieBuilder(kfs).buildAll();
if (kb.getResults().hasMessages(Message.Level.ERROR)) {
for (Message result : kb.getResults().getMessages()) {
log.info("Error: " + result.getText());
}
throw new RegnatorException("Unable to create KJar for requested conditions resources", RegnatorError.ErrorCode.UNDEFINED);
}
InternalKieModule kieModule = (InternalKieModule) kieServices.getRepository().getKieModule(releaseId);
byte[] jar = kieModule.getBytes();
return jar;
}
Thanks a lot for your response raphaëλ. But my problem was rather building the jar before being able to use it in Java code.
This is how I could solve my problem.
Creation of a kjar file with the rules :
the file must contain :
file kmodule.xml in directory META-INF
file MANIFEST.MF in directory META-INF (not sure this is necessary...)
DRL files in same path than the one defined by their package (I have put the DRL files without compiling them before and they have been fired as expected)
a file pom.xml should be present for Maven but this has failed and I had to use an external pom.xml
command :
jar cvmf META-INF\MANIFEST.MF example-rules.jar META-INF* rules*
Example of file kmodule.xml :
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="base1" default="true" packages="rules">
<ksession name="session1" type="stateful" ="true"/>
</kbase>
</kmodule>
File MANIFEST.MF :
Manifest-Version: 1.0
Add kjar to Maven repository :
command :
mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile=example-rules.jar -DpomFile=pom_jar.xml
file pom_jar.xml is used to define Maven references, example of such a file :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId> test.example</groupId>
<artifactId>example-rules</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>example-rules</name>
<!-- Output to jar format -->
<packaging>jar</packaging>
</project>
Any comment is welcome.
I am using Gradle to generate jaxb classes in my project. Every thing is working fine but while marshalling the jaxb object we are seeing different namespaces prefixes like ns1, ns2 .. randomly in the output xml. But we dont want this and want to specify specific namespace prefixes for each namespace. I checked here and found the link 15772478 saying we have to have package-info class with xmlns element, How can i say to xjc binding compiler to add xmlns element with prifixes and namespaceURI? below is the gradle configuration i have to generate Jaxb classes from schemas.
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath:configurations.jaxb.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(destdir: '${jaxbTargetDir}', binding: 'xjc-bindings/bindings.jaxb', extension: true) {
//arg(value: '-npa')
arg(value: '-readOnly')
arg(value: file('src/main/webapp/schemas/primary1.xsd'))
arg(value: file('src/main/webapp/schemas/primary2.xsd'))
arg(value: file('xjc-bindings/xjc-a.xsd'))
arg(value: file('xjc-bindings/xjc-b.xsd'))
}
sample package-info.java generated by xjc binding.
#XmlSchema(namespace = "urn:neustar:names:decedm:1.0")
package biz.neustar.dece.xml.jaxb.decedm;
import javax.xml.bind.annotation.XmlSchema;
I am expecting the package-info class like below.
#XmlSchema(namespace = "<someuri>",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(prefix="someprefix" , namespaceURI = "<some uri>")
})
package biz.neustar.dece.xml.jaxb.core;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
Can somebody please suggest me what is the configuration need to achieve this?
I don't want to use NamespacePrefixMapper to specify the prefixes.
You need to update you binding file like following. It will use eCH-0007 as prefix.
<?xml version="1.0"?>
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd
http://jaxb2-commons.dev.java.net/namespace-prefix http://java.net/projects/jaxb2-commons/sources/svn/content/namespace-prefix/trunk/src/main/resources/prefix-namespace-schema.xsd">
<jxb:bindings schemaLocation="eCH-0007-3-0.xsd">
<jxb:schemaBindings>
<jxb:package name="ch.ech.ech0007.v3" />
</jxb:schemaBindings>
<jxb:bindings>
<namespace:prefix name="eCH-0007" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
You can check complete example on this link Namespace-prefix.
Is there a way to create entirely new schema on every case?
Using #DatabaseTearDown annotation is not the case here because i need to reset
id generators as some of my test expectation rely on them (maybe it's a bad practice)
Update on rearrange my tests:
In one of my expected datasets i have:
<field oid="1" type="enumerated" name="simple enum field"
dict_oid="1" required="0"
level="1"/>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
where oid in term table is the generated id. I want to be sure that there are 3 rows were created in field_enum_element table but if i omit generated ids from expected data set as follows:
<field type="enumerated" name="simple enum field"
dict_oid="1" required="0"
level="1"/>
<field_enum_element></field_enum_element>
<field_enum_element></field_enum_element>
<field_enum_element></field_enum_element>
spring-test-db-unit thinks that there are 0 rows in the table
UPDATE:
#Test
#DatabaseSetup(value = "fieldServiceImplTest/testCreateEnumField.xml")
#ExpectedDatabase(value = "fieldServiceImplTest/testCreateEnumField.expected.xml",
assertionMode = DatabaseAssertionMode.NON_STRICT)
#DatabaseTearDown(value = "fieldServiceImplTest/clear.xml", type = DELETE_ALL)
public void testCreateEnumField() {
FieldDTO fieldDTO = new FieldDTO();
fieldDTO.setName("simple enum field");
fieldDTO.setType("enumerated");
fieldDTO.setLevel("term");
fieldDTO.setIsValueRequired(false);
fieldDTO.setDictionaryId(dictionaryService.findByOid(1L).get().returnIdentity());
List<ItemDTO> itemDTOs = Arrays.asList(new ItemDTO(null, "complete"), new ItemDTO(null, "draft"), new ItemDTO(null, "deleted"));
fieldDTO.setItems(new HashSet<>(itemDTOs));
fieldService.createField(fieldDTO);
}
testCreateEnumField.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<dictionary changed="2014-01-31 18:11:54" oid="1" client_oid="1" descr="descr" name="dictionary"/>
</dataset>
testCreateEnumField.expected.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset reset_sequences="hibernate_sequence">
<dictionary changed="2014-01-31 18:11:54" oid="1" client_oid="1" descr="descr" name="dictionary"/>
<field client_oid="1" oid="1" type="enumerated" name="simple enum field"
dict_oid="1" required="0"
level="1"></field>
<enum_element oid="11" client_oid="1" value="deleted"></enum_element>
<enum_element oid="12" client_oid="1" value="draft"></enum_element>
<enum_element oid="13" client_oid="1" value="complete"></enum_element>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
</dataset>
Ideally i would like to be able to drop sequence between tests and test cases.
Although I don't exactly know what your use case is, it sounds like it's a good fit for trying the new declarative SQL feature in Spring 4.1 RC1. Here is the JIRA issue that describes what this new feature.
Your code would look something like:
#Test
#Sql("fix-sequence.sql")
public void test() {
//whatever
}
You can find the Javadoc of #Sql here.
Inside fix-sequence.sql you would provide the SQL needed for resetting the db for the tests
I was able to manage the problem by doing a little workaround by dropping sequence table in #Before method with simple native sql query: "drop table hibernate_sequence".
Actually, the better solution is just to include <hibernate_sequence next_val="1"/> into test dataset at #DatabaseSetup phase
I'm using Selenium Webdriver (ver 2.31.2.0) (.Net) and I'm trying to extract an element (XML) which is returning from the `driver.PageSource'.
My Question: How to get the list of items using the below xpath.
I able to play in FF using XPATH addons but the same code does not work in Selenium Webdriver
any help?
Here is my code in Selenium Webdriver:
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
string _page_source = driver.PageSource;
ReadOnlyCollection<IWebElement> webElements = _page_source.FindElementsByXPath("//response//results//items/vList");
my xml looks like this:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<meta>
</meta>
<results i:type="vList">
<name>Language</name>
<queryValue>language</queryValue>
<displayOrder>0</displayOrder>
<items>
<vList>
<name>English</name>
<displayName>English</displayName>
<displayOrder>0</displayOrder>
<items />
</vList>
<vList>
<name>Swedish</name>
<displayName>Swedish</displayName>
<displayOrder>1</displayOrder>
<items />
</vList>
</items>
</results>
</response>
You can use selenium to browse to and obtain the xml, but work with the xml using .net classes.
The driver.PageSource property is a string, and you should use .Net classes directly to parse the xml represented. Also, there is no method FindElementsByXPath() on a string object, unless this is an extension method that you have written.
Read the xml using the driver.PageSource from selenium
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
XmlReader reader = XmlReader.Create(driver.PageSource);
Or, read the xml by directly browsing to the url using
XmlReader reader = XmlReader.Create("http://website_name/languages.xml");
And then use below code to parse and read the xml.
Key point to note is how the namespace information is provided to the xpath.
//load xml document
XElement xmlDocumentRoot = XElement.Load(reader);
//also add the namespace infn, chose a prefix for the default namespace
XmlNameTable nameTable = reader.NameTable;
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("a", "http://schemas.datacontract.org/2004/07/myproj.cnn.com");
//now query with your xml - remeber to prefix the default namespace
var items = xmlDocumentRoot.XPathSelectElements("//a:results/a:items/a:vList", namespaceManager);
Console.WriteLine("vlist has {0} items.", items.Count());
foreach (var item in items)
{
Console.WriteLine("Display name: {0}", item.XPathSelectElement("a:displayName",namespaceManager).Value);
}
// OR get a list of all display names using linq
var displayNames = items.Select(x => x.XPathSelectElement("a:displayName", namespaceManager).Value).ToList();
You will need the following namespaces for the above to work:
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
The XML input you have posted has a namespace declared: xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com". See the next line:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
Because this namespace has no prefix it is the default namespace for all elements without a prefix. Which means element <response> and element <results> etc all belong to this namespace.
Read next: http://www.w3schools.com/xml/xml_namespaces.asp
So in you code you need to declare the namespace before any XPath evaluation will work. I do not know how to set the namespace in Selenium Webdriver but you can find it I guess.
Once you declared the namespace you need to use this in your XPath. For example in a XSLT you can declare the namespace as follows:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:foo="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
I now declared the namespace with prefix foo. The XPath that can be used to retrieve all vList elements would be:
/foo:response/foo:results/foo:items/foo:vList
To get all displayName elements you can use:
/foo:response/foo:results/foo:items/foo:vList/foo:displayName
If you want the total count of the elements instead of the list of elements, you can wrap count() around it like:
count(/foo:response/foo:results/foo:items/foo:vList)
count(/foo:response/foo:results/foo:items/foo:vList/foo:displayName)
The XPath you used has a lot of // in it. Only use // if it is really necessary, because it will scan the complete file and takes more resources than necessary if you know the path already.