更新 XML 节点属性失败,使用 XSLT 1.0

huangapple 未分类评论48阅读模式
英文:

Failed to Update XML Node Attribute using XSLT 1.0

问题

我正在使用Java 8与XSLT 1.0

我有以下XML文件用作XSLT的输入

    <?xml version="1.0" encoding="UTF-8"?>
    <Research xmlns="http://www.rixml.org/2013/2/RIXML">
        <Product>
            <StatusInfo statusType="Revised"/>
        </Product>
    </Research>

我尝试将statusType属性从当前值更新为Deleted以下是执行此操作的XSLT

<xsl:stylesheet version="1.0" xmlns="http://www.rixml.org/2013/2/RIXML" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no" encoding="UTF-8" />

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//Research/Product/StatusInfo">
        <xsl:element name="StatusInfo">
            <xsl:attribute name="statusType">Deleted</xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

但是当我尝试使用以下Java程序应用XSLT时虽然没有报错但无法成功更新新生成的xml中的statusType属性

只要我移除Research元素的xmlns属性并应用相同的XSLT它就能正确地更新属性

我正在使用以下Java程序将XSLT应用于输入文件以生成最终的输出文件

public class TestPullbackRIXMLXSLT1 {

    private static final String SOURCE_XSLT_PATH="C:\\MDERedesignPoc\\distribution-engine-publications\\package\\config\\xslt\\RIXMLPullback.xsl";
    private static final String INPUT_XML_FILE_PATH="C:\\export\\rschapps\\rschdistengine\\workarea-qa\\2002434_1_10893_DISTRIBUTE\\core\\input.xml";
    private static final String OUTPUT_XML_FILE_PATH="C:\\export\\rschapps\\rschdistengine\\workarea-qa\\2002434_1_10893_DISTRIBUTE\\core\\output.xml";
    private static final Logger logger = LoggerFactory.getLogger(TestRIXMLXSLT.class);

    public static void main(String[] args) {

        try
        {

            System.out.println("Creation of RIXML 24 ");
            Transformer transformer = createTransformer();
            StreamSource source = new StreamSource(new File(INPUT_XML_FILE_PATH));
            File outputXML=new File(OUTPUT_XML_FILE_PATH);
            StreamResult result = new StreamResult(outputXML);
            transformer.transform(source, result);

        }
        catch(Exception e) {
            e.printStackTrace();
        }

    }
    private static Transformer createTransformer() throws TransformerConfigurationException{
        TransformerFactory factory = TransformerFactory.newInstance();
        factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "all");
        factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "all");
        Templates cachedXSLT = factory.newTemplates(new StreamSource(new File(SOURCE_XSLT_PATH)));
        Transformer transformer = cachedXSLT.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, Constants.YES);
        transformer.setOutputProperty(Constants.TRANSFORMER_INDENT_PARAMETER_NAME, Constants.TRANSFORMER_INDENT_PARAMETER_VALUE);
        return transformer;
    }
}

我无法理解为什么xmlns会导致应用XSLT时出现问题,而没有属性时一切都正常工作。

为了避免失败,我必须在input.xml中保留xmlns(命名空间)属性。

有人能帮我解决这个问题吗?

英文:

I am using Java 8 with XSLT 1.0.

I have the below xml file used as input to XSLT

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;Research xmlns=&quot;http://www.rixml.org/2013/2/RIXML&quot;&gt;
	&lt;Product&gt;
		&lt;StatusInfo statusType=&quot;Revised&quot;/&gt;
	&lt;/Product&gt;
&lt;/Research&gt;

I am trying to update the statusType attribute to Deleted from the current value and below is the xslt doing the same.

<xsl:stylesheet version="1.0" xmlns="http://www.rixml.org/2013/2/RIXML" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no" encoding="UTF-8" />

&lt;xsl:template match=&quot;node()|@*&quot;&gt;
	&lt;xsl:copy&gt;
		&lt;xsl:apply-templates select=&quot;node()|@*&quot; /&gt;
	&lt;/xsl:copy&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match=&quot;//Research/Product/StatusInfo&quot;&gt;
	&lt;xsl:element name=&quot;StatusInfo&quot;&gt;
		&lt;xsl:attribute name=&quot;stausType&quot;&gt;Deleted&lt;/xsl:attribute&gt;
	&lt;/xsl:element&gt;
&lt;/xsl:template&gt;

</xsl:stylesheet>

But when I try to apply xslt using below Java program it is not giving any error but it is failing to update the statusType in newly generated xml.

As soon as I removed the xmlns attribute of Research element and apply the same xslt it is updating the attribute properly.

I am using below Java program to apply xslt on the input file to generate the final output file.

public class TestPullbackRIXMLXSLT1 {

private static final String SOURCE_XSLT_PATH=&quot;C:\\MDERedesignPoc\\distribution-engine-publications\\package\\config\\xslt\\RIXMLPullback.xsl&quot;;
private static final String INPUT_XML_FILE_PATH=&quot;C:\\export\\rschapps\\rschdistengine\\workarea-qa\\2002434_1_10893_DISTRIBUTE\\core\\input.xml&quot;;
private static final String OUTPUT_XML_FILE_PATH=&quot;C:\\export\\rschapps\\rschdistengine\\workarea-qa\\2002434_1_10893_DISTRIBUTE\\core\\output.xml&quot;;
private static final Logger logger = LoggerFactory.getLogger(TestRIXMLXSLT.class);

public static void main(String[] args) {
	
	try
	{
		
		System.out.println(&quot;Creation of RIXML 24 &quot;);
		Transformer transformer = createTransformer();
		StreamSource source = new StreamSource(new File(INPUT_XML_FILE_PATH));
	    File outputXML=new File(OUTPUT_XML_FILE_PATH);
	    StreamResult result = new StreamResult(outputXML);
	    transformer.transform(source, result);
    
	}
	catch(Exception e) {
		e.printStackTrace();
	}
	
}
private static Transformer createTransformer() throws TransformerConfigurationException{
	TransformerFactory factory = TransformerFactory.newInstance();
	factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, &quot;all&quot;);
	factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, &quot;all&quot;);
	Templates cachedXSLT = factory.newTemplates(new StreamSource(new File(SOURCE_XSLT_PATH)));
	Transformer transformer = cachedXSLT.newTransformer();
	transformer.setOutputProperty(OutputKeys.INDENT, &quot;yes&quot;);
	transformer.setOutputProperty(OutputKeys.INDENT, Constants.YES);
	transformer.setOutputProperty(Constants.TRANSFORMER_INDENT_PARAMETER_NAME, Constants.TRANSFORMER_INDENT_PARAMETER_VALUE);
	return transformer;
}

}

I am not able to understand why xmlns is causing the issue while applying the xslt and if attribute is not present everything is working fine.

I have to keep the xmlns (namespace) attribute in input.xml to avoid failures.

Can anybody please help me fix this issue?

答案1

得分: 0

以下是翻译好的内容:

这种问题经常会出现。您需要考虑命名空间。在命名空间上做一些阅读。

可以像这样完成:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:ri="http://www.rixml.org/2013/2/RIXML"
	version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="//ri:Research/ri:Product/ri:StatusInfo">
    <xsl:element name="StatusInfo" namespace="http://www.rixml.org/2013/2/RIXML">
        <xsl:attribute name="statusType">Deleted</xsl:attribute>
    </xsl:element>
  </xsl:template>
  
</xsl:stylesheet>

在这里查看它的工作示例:https://xsltfiddle.liberty-development.net/ehVZvw8

或者你可以简化成这样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:ri="http://www.rixml.org/2013/2/RIXML"
	version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ri:StatusInfo/@statusType">
    <xsl:attribute name="statusType">Deleted</xsl:attribute>
  </xsl:template>
  
</xsl:stylesheet>

在这里查看它的工作示例:https://xsltfiddle.liberty-development.net/ehVZvw8/1

英文:

This question kind of questions comes back very often. You need to take into account the namespace. Do some reading on namespaces.

It can be done like this:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;
	xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;
	xmlns:ri=&quot;http://www.rixml.org/2013/2/RIXML&quot;
	version=&quot;1.0&quot;&gt;

  &lt;xsl:output method=&quot;xml&quot; indent=&quot;yes&quot;/&gt;

  &lt;xsl:template match=&quot;node()|@*&quot;&gt;
    &lt;xsl:copy&gt;
        &lt;xsl:apply-templates select=&quot;node()|@*&quot; /&gt;
    &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;

  &lt;xsl:template match=&quot;//ri:Research/ri:Product/ri:StatusInfo&quot;&gt;
    &lt;xsl:element name=&quot;StatusInfo&quot; namespace=&quot;http://www.rixml.org/2013/2/RIXML&quot;&gt;
        &lt;xsl:attribute name=&quot;statusType&quot;&gt;Deleted&lt;/xsl:attribute&gt;
    &lt;/xsl:element&gt;
  &lt;/xsl:template&gt;
  
&lt;/xsl:stylesheet&gt;

See it working here: https://xsltfiddle.liberty-development.net/ehVZvw8

Or you could simplify it to this:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;
	xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;
	xmlns:ri=&quot;http://www.rixml.org/2013/2/RIXML&quot;
	version=&quot;1.0&quot;&gt;

  &lt;xsl:output method=&quot;xml&quot; indent=&quot;yes&quot;/&gt;

  &lt;xsl:template match=&quot;node()|@*&quot;&gt;
    &lt;xsl:copy&gt;
      &lt;xsl:apply-templates select=&quot;node()|@*&quot; /&gt;
    &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;

  &lt;xsl:template match=&quot;ri:StatusInfo/@statusType&quot;&gt;
    &lt;xsl:attribute name=&quot;statusType&quot;&gt;Deleted&lt;/xsl:attribute&gt;
  &lt;/xsl:template&gt;
  
&lt;/xsl:stylesheet&gt;

See it working here: https://xsltfiddle.liberty-development.net/ehVZvw8/1

huangapple
  • 本文由 发表于 2020年5月19日 21:07:11
  • 转载请务必保留本文链接:https://java.coder-hub.com/61891809.html
匿名

发表评论

匿名网友

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

确定