英文:
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
<?xml version="1.0" encoding="UTF-8"?>
<Research xmlns="http://www.rixml.org/2013/2/RIXML">
<Product>
<StatusInfo statusType="Revised"/>
</Product>
</Research>
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" />
<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="stausType">Deleted</xsl:attribute>
</xsl:element>
</xsl:template>
</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="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;
}
}
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:
<?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>
See it working here: https://xsltfiddle.liberty-development.net/ehVZvw8
Or you could simplify it to this:
<?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>
See it working here: https://xsltfiddle.liberty-development.net/ehVZvw8/1
专注分享java语言的经验与见解,让所有开发者获益!
评论