Search code examples
javaxslt-1.0xslt-2.0xmlunitxmlunit-2

getting 'ERROR: 'Syntax error in '. castable as xs:integer' while Trying to transform xml, based on Data type of value the tag is containing


here is my _ignoreText.xsl file

<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="no" />
        <xsl:template match="*|@*|text()|comment()|processing-instruction()" >
    
            <xsl:if test="normalize-space(.) != '' or ./@* != ''">
                <xsl:copy>
                    <xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
                </xsl:copy>
            </xsl:if>
    
            <xsl:variable name="type">
                <xsl:choose>
                    <xsl:when test=". castable as xs:integer">
                        <xsl:text>Integer</xsl:text>
                    </xsl:when>
                    <xsl:when test=". castable as xs:boolean">
                        <xsl:text>Boolean</xsl:text>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text>String</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
    
    
        </xsl:template>
    
    </xsl:stylesheet>

below is a java code in which i am using above _ignoreText.xsl file to transform xml

import org.custommonkey.xmlunit.Transform;
import java.io.File;


public class TransformDemo1 {
    public static void main(String args[]) throws Exception {

        String xsltfilename="D:\\Demo\\src\\test\\java\\StringXml\\_ignoreText.xsl";
        File xsltfile=new File(xsltfilename);

        String strSource = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
                "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\" xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\">\n" +
                "    <SOAP-ENV:Body>\n" +
                "        <return>\n" +
                "            <ICD10Flag>hello</ICD10Flag>\n" +
                "            <status>success</status>\n" +
                "        </return>\n" +
                "    </SOAP-ENV:Body>\n" +
                "</SOAP-ENV:Envelope>\n";
        Transform docSource = new Transform(strSource, xsltfile);

    }
}

following is the Error i am getting.

ERROR:  'Syntax error in '. castable as xs:integer'.'
FATAL ERROR:  'file:/D:/Demo/src/test/java/StringXml/_ignoreText.xsl: line 18: Required attribute 'test' is missing.'
Exception in thread "main" org.custommonkey.xmlunit.exceptions.ConfigurationException: file:/D:/RijvanPactPOC/2/DemoProjectPactConsumer/src/test/java/StringXml/_ignoreText.xsl: line 18: Required attribute 'test' is missing.
    at org.custommonkey.xmlunit.Transform.getTransformer(Transform.java:201)
    at org.custommonkey.xmlunit.Transform.<init>(Transform.java:161)
    at org.custommonkey.xmlunit.Transform.<init>(Transform.java:92)
    at StringXml.TransformDemo1.main(TransformDemo1.java:31)
Caused by: javax.xml.transform.TransformerConfigurationException: file:/D:/Demo/src/test/java/StringXml/_ignoreText.xsl: line 18: Required attribute 'test' is missing.
    at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:1061)
    at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:817)
    at org.custommonkey.xmlunit.Transform.getTransformer(Transform.java:196)
    ... 3 more

Process finished with exit code 1

please suggest any solution or any other Library using that i can Transform the XML based the data type of the value the xml tag is containing

Ex. 1

<status>success</status>

should be transformed to

<status>String</status>

Ex. 2

<status>123</status>

should be transformed to

<status>Integer</status>

Solution

  • Looks like you are trying to match the XML with node content's data type.

    If that is the case you can use the custom DifferenceEvaluator as below.

    public class XMLUnitDiffDemo{
    
    public static void main(String args[]) throws Exception {
      String strSource = "<root><test>true</test>" +
                    "<test2>2</test2>" +
                    "<test1>1</test1>" +
                    "</root>";
      String strTest = "<root><test>true</test>" +
                    "<test1>1</test1>" +
                    "<test2>2</test2>" +
                    "</root>";
    
    
     Diff myDiff = DiffBuilder.compare(xmlSource).withTest(xmlCompareWith)
                    .ignoreComments()
                    .ignoreWhitespace()
                    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
                    .withDifferenceEvaluator(new DataTypeElementDifferenceEvaluator())
                    .checkForSimilar().build();
    
    System.out.println(!myDiff.hasDifferences())
    }
    }
    

    Custom implementation.

    
    class DataTypeElementDifferenceEvaluator implements DifferenceEvaluator {
    
        @Override
        public ComparisonResult evaluate(Comparison comparison, ComparisonResult outcome) {
            if (outcome == ComparisonResult.EQUAL) return outcome; // only evaluate differences.
            Node controlNode = comparison.getControlDetails().getTarget();
            Node testNode = comparison.getTestDetails().getTarget();
            String controlnodename = controlNode.getNodeName();
            String testNodename = testNode.getNodeName();
            String conCN = controlNode.getTextContent();
            String conTN = testNode.getTextContent();
            if(controlnodename.equalsIgnoreCase(testNodename)){
                System.out.println(getDataType(conCN) + " ==  " + getDataType(conTN));
                if(getDataType(conCN).equalsIgnoreCase(getDataType(conTN))) {
                    return ComparisonResult.SIMILAR;
                }
            }
            return outcome;
        }
    
    public static String getDataType(String input) {
    
            String dataType = null;
            // checking for Integer
            if (input.matches("\\d+")) {
                dataType = "java.lang.Integer";
            }
            // checking for floating point numbers
            else if (input.matches("\\d*[.]\\d+")) {
                dataType = "java.lang.Double";
            }
            // checking for date format dd/mm/yyyy
            else if (input.matches(
                    "\\d{2}[/]\\d{2}[/]\\d{4}")) {
                dataType = "java.util.Date";
            }
            // checking for date format mm/dd/yyyy
            else if (input.matches(
                    "\\d{2}[/]\\d{2}[/]\\d{4}")) {
                dataType = "java.util.Date";
            }
            // checking for date format dd-mon-yy
            else if (input.matches(
                    "\\d{2}[-]\\w{3}[-]\\d{2}")) {
                dataType = "java.util.Date";
            }
            // checking for date format dd-mon-yyyy
            else if (input.matches(
                    "\\d{2}[-]\\w{3}[-]\\d{4}")) {
                dataType = "java.util.Date";
            }
            // checking for date format dd-month-yy
            else if (input.matches("\\d{2}[-]\\w+[-]\\d{2}")) {
                dataType = "java.util.Date";
            }
            // checking for date format dd-month-yyyy
            else if (input.matches("\\d{2}[-]\\w+[-]\\d{4}")) {
                dataType = "java.util.Date";
            }
            // checking for date format yyyy-mm-dd
            else if (input.matches(
                    "\\d{4}[-]\\d{2}[-]\\d{2}")) {
                dataType = "java.util.Date";
            }
            // checking for String
            else {
                dataType = "java.lang.String";
            }
    
            return dataType;
    
        }
    
    }