【问题标题】:Failed to Update XML Node Attribute using XSLT 1.0 [duplicate]无法使用 XSLT 1.0 更新 XML 节点属性 [重复]
【发布时间】:2020-05-19 13:07:11
【问题描述】:

我正在使用带有 XSLT 1.0 的 Java 8。

我将以下 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: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>

但是当我尝试使用下面的 Java 程序应用 xslt 时,它没有给出任何错误,但它无法更新新生成的 xml 中的 statusType。

只要我删除了 Research 元素的 xmlns 属性并应用相同的 xslt,它就会正确更新该属性。

我正在使用下面的 Java 程序在输入文件上应用 xslt 以生成最终的输出文件。

公共类 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;
}

}

我无法理解为什么在应用 xslt 时 xmlns 会导致问题,如果属性不存在,一切正常。

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

谁能帮我解决这个问题?

【问题讨论】:

    标签: java xml xslt xslt-1.0


    【解决方案1】:

    这类问题经常出现。您需要考虑命名空间。阅读命名空间。

    可以这样做:

    <?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

    【讨论】:

    • @Sebastian 感谢您解决我的问题。我肯定会更多地关注名称空间。我只是想再确认一个重新升级 xsl:copy 标记的东西,它是否会在将源 xml 节点复制到结果 xml 时复制任何 CDATA 部分(如果它们存在于源 xml 中)。如果没有,有什么办法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    相关资源
    最近更新 更多