Change attribute value without creating new output

2019-08-13 14:43发布

I need to iterate over a bunch of XML documents and simply change the value of one attribute using XSLT 2.0. The rest of the document as well as the document name need to be the same.

Is it possible to simply change an existing document without creating a new one as output of the transformation? Or do I need to copy the documents, change the attribute and name them the same as the original one?

EDIT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:fn='http://www.w3.org/2005/xpath-functions' exclude-result-prefixes='xsl xs fn' xmlns:h="http://java.sun.com/jsf/html">
    <xsl:output method="xml" encoding="utf-8"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="files" select="collection('./output?select=*.html')"/>

    <xsl:template match="/">
        <xsl:for-each select="$files">
            <xsl:variable name="fileName" select="tokenize(base-uri(), '/')[last()]"/>
            <xsl:result-document method="xhtml" href="new/{$fileName}">
                <div>
                    <h:selectBooleanCheckbox value="pubs"/>
                    <xsl:copy>
                        <xsl:apply-templates select="@* | node()"/>
                    </xsl:copy>
                </div>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="@src">
        <xsl:variable name="folderName" select="tokenize(base-uri(), '/')[last()-2]"/>
        <xsl:text>http://localserver.com/</xsl:text>
        <xsl:value-of select="$folderName"/>
        <xsl:text>/output/</xsl:text>
        <xsl:value-of select="."/>
    </xsl:template>
</xsl:stylesheet>

It doesn't work. Only the textnodes are selected. How can I get this to work?

1条回答
男人必须洒脱
2楼-- · 2019-08-13 15:14

No, it is not possible to change the input XML document in place.

XSLT transforms input XML to an output file, often also XML; it never modifies a file in place.

Your goal is easily obtained via the identity transformation,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

plus one template to match the attribute you wish to change:

  <xsl:template match="@oldAttName">
    <xsl:attribute name="newAttName">newAttValue</xsl:attribute>
  </xsl:template>

Of course, the match criteria can be as complicated as needed, and the new attribute value could be derived from data in the input XML rather than fixed, but this illustrates the basic general pattern of how to change an attribute.

If you need the resultant output document to be named the same as the input document, you can do so with a script/batch file/calling program after XSLT finishes.

查看更多
登录 后发表回答