In Java , no TransformerException is thrown while performing XSLT transformation when I send a bad XML ( XML with no tags mentioned in XSLT)

huangapple go评论77阅读模式
英文:

In Java , no TransformerException is thrown while performing XSLT transformation when I send a bad XML ( XML with no tags mentioned in XSLT)

问题

In Java,在使用XSLT文件将一个XML转换为另一个XML时,如果输入是一个坏的XML(负面测试),不会抛出TransformerException异常。

坏的XML是指一个XML没有XSLT文件期望的标签。
坏XML示例:

<Sample>123</Sample>

XSLT快照(请注意,Sample在此处未在任何地方指定为标签):

*<xsl:template match="/SammpleReply" xpath-default-namespace="SammpleReply" exclude-result-prefixes="#all">
...
*</RadialReply>*

输入:

<Sample>202008131228</Sample>

输出:

<?xml version="1.0" encoding="UTF-8"?>202008131228

期望结果: 如果传入的XML在XSLT中没有定义任何XML元素,应该抛出异常(但实际上没有抛出)。想要知道原因,并希望在这种情况下代码抛出异常。以下是可能实现这一目标的代码逻辑:

代码只加载XSLT文件并进行转换,不进入异常块。它成功进行了转换,而outputResultStr是上面的输出。

Reader xmlReader = new StringReader(payloadStr);
StringWriter stringWriter = new StringWriter();
Result result = new StreamResult(stringWriter);
try {
    transformer.transform(new StreamSource(xmlReader), result);
    outputResultStr = stringWriter.toString();
} catch (TransformerException trEx) {
    // 处理异常的代码逻辑
}

如果要使代码在没有XSLT定义的XML元素时抛出异常,可以在catch块中添加适当的逻辑来检查输出是否为空或无效,然后抛出自定义异常或其他异常类型。

英文:

In Java , while transforming one XML into another XML using an XSLT file , when given a bad XML as input ( negative testing) no TransformerException is thrown.

Bad XML here is an XML with no tags which XSLT expects
Example of Bad XML
<Sample>123</Sample>

XSLT snapshot ( Note Sample is not a tag specified anywhere here )

 *&lt;xsl:template match=&quot;/SammpleReply&quot; xpath-default-namespace=&quot;SammpleReply&quot; exclude-result-prefixes=&quot;#all&quot;&gt;
       &lt;RadialReply xmlns=&quot;http://SammpleReply.com&quot;&gt;
            &lt;xsl:choose&gt;
                &lt;xsl:when test=&quot;PaymentContextBase&quot;&gt;
                   &lt;PaymentContextBase&gt;
                       &lt;OrderId&gt;&lt;xsl:value-of select=&quot;RadialReply/Radial:RadialReplySessionId&quot;/&gt;&lt;/OrderId&gt;
                   &lt;/PaymentContextBase&gt;
                   &lt;TenderType&gt;&lt;xsl:value-of select=&quot;RadialReply/Radial:TenderType&quot;/&gt;&lt;/TenderType&gt;
                &lt;/xsl:when&gt;
               &lt;xsl:otherwise&gt;
                    &lt;RadialReplyContext&gt;
                        &lt;OrderId&gt;&lt;xsl:value-of select=&quot;RadialContext/payment:RadialUniqueId&quot;/&gt;&lt;/OrderId&gt;
                         &lt;xsl:element name=&quot;RadialUniqueId&quot; &gt;
                            &lt;xsl:attribute name=&quot;isToken&quot;&gt;&lt;xsl:value-of select=&quot;RadialContext/payment:PaymentAccountUniqueId/@isToken&quot;/&gt;&lt;/xsl:attribute&gt;
                            &lt;xsl:value-of select=&quot;RadialContext/payment:RadialUniqueId&quot;/&gt;
                         &lt;/xsl:element&gt;
                    &lt;/RadialReplyContext&gt;
                   &lt;TenderType&gt;&lt;xsl:value-of select=&quot;PaymentContext/payment:TenderType&quot;/&gt;&lt;/TenderType&gt;
               &lt;/xsl:otherwise&gt;
            &lt;/xsl:choose&gt;
            &lt;SlotsAvailable&gt;&lt;xsl:value-of select=&quot;SlotsAvailability&quot;/&gt;&lt;/SlotsAvailable&gt;
           &lt;xsl:choose&gt;
                &lt;xsl:when test=&quot;Reattempt&quot;&gt;
                    &lt;ReauthorizationAttempted&gt;&lt;xsl:value-of select=&quot;ReattemptValue&quot;/&gt;&lt;/ReauthorizationAttempted&gt;
                &lt;/xsl:when&gt;
           &lt;/xsl:choose&gt;
       &lt;/RadialReply&gt;*

Input

&lt;Sample&gt;202008131228&lt;/Sample&gt;

Output

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;202008131228

Desired Result : If an incoming XML does not have any XML element defined in XSLT . Exception should be thrown ( Which is not happening ) Need to know why and I want the code to throw an exception in this case . What code logic would achieve that ?
Code just loads the XSLT File and transforms it . Code does not go to exception block. it transforms successfully and String outputResultStr is the output above

 Reader xmlReader = new StringReader(payloadStr);
                StringWriter stringWriter = new StringWriter();
                Result result = new StreamResult(stringWriter);
                transformer.transform(new StreamSource(xmlReader), result);
                outputResultStr = stringWriter.toString();
                

            } catch (TransformerException trEx) {
                  } 

答案1

得分: 2

在XSLT 1.0或2.0中,添加一个模板规则:

<xsl:template match="*">
  <xsl:message terminate="yes">未知元素 <xsl:value-of select="name()"/> </xsl:message>
</xsl:template>

以匹配那些没有被任何其他模板规则匹配的元素。

在3.0中,添加 <xsl:mode on-no-match="fail"/>

之所以没有失败的原因是,XSLT定义了一个默认模板规则,用于处理未被样式表中的任何其他模板规则匹配的元素。

英文:

In XSLT 1.0 or 2.0, add a template rule

&lt;xsl:template match=&quot;*&quot;&gt;
  &lt;xsl:message terminate=&quot;yes&quot;&gt;Unknown element &lt;xsl:value-of select=&quot;name()&quot;/&gt;&lt;/xsl:message&gt;
&lt;/xsl:template&gt;

to match elements that are not matched by any other template rule.

In 3.0, add &lt;xsl:mode on-no-match=&quot;fail&quot;/&gt;.

The reason it's not failing is that XSLT defines a default template rule to process elements that are not matched by any other template rule in the stylesheet.

答案2

得分: 0

xsl transform 将会通过,即使没有匹配的标签。

有几个选项...

  • 重构 xsl 来匹配 / 并查找所需/允许的标签,如果找不到,则使用 &lt;xsl:message terminate=&quot;yes&quot;/&gt; 抛出错误
  • 为输入的 XML 创建 XML 模式并在转换之前进行验证
英文:

xsl transform will pass even if there are no matching tags.

There are several options ...

  • refactor xsl to match / and look for desired/allowed tags and throw error using &lt;xsl:message terminate=&quot;yes&quot;/&gt; if not found
  • create xml schema for input xml an validate before transform

答案3

得分: 0

您可以在XSLT转换之前实现SAX模式验证API。

这是我的SAX验证程序,指定要验证XML输入数据的模式:

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

InputSourceHandle saxHandle = new InputSourceHandle();

saxHandle.setErrorHandler(new InputSourceHandle.DraconianErrorHandler());

String procSchema =
    "<?xml version='1.0' encoding='UTF-8'?>" +
    "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' " +
        "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
        "xsi:schemaLocation='http://www.w3.org/2001/XMLSchema XMLSchema.xsd'>" +
      "<xs:element name='ProcedureDocument'>" +
        "<xs:complexType mixed='true'>" +
          "<xs:choice minOccurs='0' maxOccurs='unbounded'>" +
            "<xs:element name='title'/>" +
            "<xs:element name='confidentialityCode'/>" +
            "<xs:element name='originalText'/>" +
            "<xs:element name='statusCode'/>" +
            "<xs:element name='methodCode'/>" +
            "<xs:element name='reference'/>" +
          "</xs:choice>" +
          "<xs:attribute name='value' type='xs:string' use='optional'/>" +
        "</xs:complexType>" +
      "</xs:element>" +
    "</xs:schema>";

Schema schema = factory.newSchema(new StreamSource(new StringReader(procSchema)));

saxHandle.setDefaultWriteSchema(schema);
// 继续进行XSLT转换

一个格式良好且有效的XML文件示例:

<?xml version="1.0" encoding="utf-8"?>
<ProcedureDocument>
    <title>Procedures Anesthesia</title>
    <confidentialityCode>Confidential</confidentialityCode>
    <originalText>Cardiac Surgery :: CABG, arterial, three</originalText>
    <statusCode code="performed"/>
    <methodCode>UNK</methodCode>
    <reference value="#Procedure2"/>
</ProcedureDocument>

只需一次验证即可准确捕获所有范围的错误输入并正常退出应用程序。

例如:缺少标签</ProcedureDocument>

错误
由XML解析器处理null时报告的错误:cvc-elt.1:找不到元素'title'的声明。:cvc-elt.1:找不到元素'title'的声明。

例如:格式不正确的元素/属性 => <reference Value="#Procedure2"/>

错误
由XML解析器处理null时报告的错误:文档中根元素之前的标记必须是格式良好的。:文档中根元素之前的标记必须是格式良好的。

例如:格式不正确的xpath/tag =>

<?xml version="1.0" encoding="utf-8"?>
ProcedureDocument
    <title>Procedures Anesthesia</title>
错误
由XML解析器处理null时报告的错误:内容不允许在前言中。:前言中不允许有内容。
英文:

You can implement SAX schema validation API before XSLT transformation.

> Here my SAX validation program specifies the schema to validate XML input data:

	SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

	InputSourceHandle saxHandle = new InputSourceHandle();
	
	saxHandle.setErrorHandler(new InputSourceHandle.DraconianErrorHandler());
		    
	String procSchema =
	      &quot;&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;&quot; +
	      &quot;&lt;xs:schema xmlns:xs=&#39;http://www.w3.org/2001/XMLSchema&#39; &quot; +
	          &quot;xmlns:xsi=&#39;http://www.w3.org/2001/XMLSchema-instance&#39; &quot; +
	          &quot;xsi:schemaLocation=&#39;http://www.w3.org/2001/XMLSchema XMLSchema.xsd&#39;&gt;&quot; +
	        &quot;&lt;xs:element name=&#39;ProcedureDocument&#39;&gt;&quot; +
	          &quot;&lt;xs:complexType mixed=&#39;true&#39;&gt;&quot; +
	            &quot;&lt;xs:choice minOccurs=&#39;0&#39; maxOccurs=&#39;unbounded&#39;&gt;&quot; +
	              &quot;&lt;xs:element name=&#39;title&#39;/&gt;&quot; +
	              &quot;&lt;xs:element name=&#39;confidentialityCode&#39;/&gt;&quot; +
	              &quot;&lt;xs:element name=&#39;originalText&#39;/&gt;&quot; +
	              &quot;&lt;xs:element name=&#39;statusCode&#39;/&gt;&quot; +		              
	              &quot;&lt;xs:element name=&#39;methodCode&#39;/&gt;&quot; +
	              &quot;&lt;xs:element name=&#39;reference&#39;/&gt;&quot; +
	            &quot;&lt;/xs:choice&gt;&quot; +
	            &quot;&lt;xs:attribute name=\&quot;value\&quot; type=&#39;xs:string&#39; use=&#39;optional&#39;/&gt;&quot; +
	          &quot;&lt;/xs:complexType&gt;&quot; +
	        &quot;&lt;/xs:element&gt;&quot; +
	      &quot;&lt;/xs:schema&gt;&quot;;

	Schema schema = factory.newSchema(new StreamSource(new StringReader(procSchema)));

saxHandle.setDefaultWriteSchema(schema);
…….
//proceed XSLT transformation

> A well-formed and valid XML file is:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;/ProcedureDocument&gt;
	&lt;title&gt;Procedures Anesthesia&lt;/title&gt;
	&lt;confidentialityCode&gt;Confidential&lt;/confidentialityCode&gt;
	&lt;originalText&gt;Cardiac Surgery :: CABG, arterial, three&lt;/originalText&gt;
	&lt;statusCode code=&quot;performed&quot;/&gt;
	&lt;methodCode&gt;UNK&lt;/methodCode&gt;
	&lt;reference value=&quot;#Procedure2&quot;/&gt;
&lt;/ProcedureDocument&gt;

Just one validation can precisely catch all range of erroneous input and exit the application gracefully.
> e.g: missing tag &lt;/ProcedureDocument&gt;

Error 
   Error reported by XML parser processing null: cvc-elt.1: Cannot find the declaration of
  element &#39;title&#39;.: cvc-elt.1: Cannot find the declaration of element &#39;title&#39;.

> e.g: ill-formed element/attribute => &lt;reference Value=&quot;#Procedure2&quot;/&gt;

Error 
   Error reported by XML parser processing null: The markup in the document preceding the
  root element must be well-formed.: The markup in the document preceding the root element
  must be well-formed.

> e.g: ill-formed xpath/tag =>

ProcedureDocument
	&lt;title&gt;Procedures Anesthesia&lt;/title&gt;
Error 
   Error reported by XML parser processing null: Content is not allowed in prolog.: Content
  is not allowed in prolog.

huangapple
  • 本文由 发表于 2020年8月13日 21:40:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63396485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定