1

I'm trying to update just finalName, artifactId and name in pom.xml using xslt. I don't understand xslt transformation, but I found this: how to modify xml file using xslt which seems very easy to follow, so based on that I created this template:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="//artifactId">
    <artifactId>aaaaaaaaaaaaaaaaaaaaaaaaaaa123</artifactId>
  </xsl:template>
</xsl:stylesheet>

and building it using:

xsltproc template.xsl pom.xml > modified-pom.xml

however for some unknown to me reason, the xpath //artifactId does not seem to be matched and replaced. I tried also: artifactId only, project/artifactId, /project/artifactId etc. but none matches. Remembering lesson from using xmlstalet which requires specific namespaces, this seems to be maybe somehow namespace related, but I really don't know how to fix it, as man xsltproc seems to be somehow broken/not reflecting command reality. Can someone help where is the error?

EDIT: added partially solved state, based on request from comment:

as an minimally working example input file , we might consider this pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <artifactId>toUpdate</artifactId>
  <name>toUpdate</name>

  <properties>
    <finalName>toUpdate</finalName>
  </properties>
</project>

I'm using now template:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://maven.apache.org/POM/4.0.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="/m:project/m:artifactId">
    <artifactId>updated</artifactId>
  </xsl:template>
  <xsl:template match="/m:project/m:name">
    <name>updated</name>
  </xsl:template>
  <xsl:template match="/m:project/m:properties/m:finalName">
    <finalName>updated</finalName>
  </xsl:template>
</xsl:stylesheet>

and replacing it using command: xsltproc template.xsl min.xml > out.xml

the output is:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <artifactId xmlns="" xmlns:m="http://maven.apache.org/POM/4.0.0">updated</artifactId>
  <name xmlns="" xmlns:m="http://maven.apache.org/POM/4.0.0">updated</name>
  <properties>
    <finalName xmlns="" xmlns:m="http://maven.apache.org/POM/4.0.0">updated</finalName>
  </properties>
</project>

where I'd like to get rid of part xmlns="" xmlns:m="http://maven.apache.org/POM/4.0.0"

if I update the replacement in template to: <m:finalName>updated</m:finalName> I'm not getting the correct result, but instead:

<m:finalName xmlns:m="http://maven.apache.org/POM/4.0.0">updated</m:finalName>

trying to declare global namespace instead of m also did not help me, as it even did not build.

Expected output is input with toUpdate replaced with updated

Martin Mucha
  • 2,385
  • 1
  • 29
  • 49
  • I think POM files use a namespace so this is probably a duplicate of all the questions on how to select and match elements in an XML file with a default namespace declaration. – Martin Honnen May 18 '20 at 15:16
  • @MartinHonnen you're correct, wasn't able to find it. Thanks for your help. I will add valid template as an answer unless you do that sooner — but it seems you do not need extra karma ;) Anyways, thanks for helping me! – Martin Mucha May 18 '20 at 15:23
  • @MartinHonnen ...however, when i declared `xmlns:os` and updated match accordingly to say `os:/project/os:artifactId` it works and even builds, but generated element is `actualValue` is there a way how to get rid of that xmlns declarad in every changed element? – Martin Mucha May 18 '20 at 15:41
  • @MartinMucha If you want the new element to be in the same namespace as the one it replaces, you must put it there. What you show in your question creates an element in no-namespace and it is correctly marked as such. If you cannot work this out, post a [mcve] showing input, XSLT and expected output. – michael.hor257k May 18 '20 at 16:07
  • added, sorry for not providing enough in first place. – Martin Mucha May 18 '20 at 16:22

1 Answers1

3

Consider the following minimized example:

XML

<project xmlns="http://maven.apache.org/POM/4.0.0">
    <artifactId>toUpdate</artifactId>
    <name>toUpdate</name>
    <properties>
        <finalName>toUpdate</finalName>
    </properties>
</project>

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:m="http://maven.apache.org/POM/4.0.0"
exclude-result-prefixes="m">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="m:artifactId">
    <artifactId>updated</artifactId>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <artifactId>updated</artifactId>
  <name>toUpdate</name>
  <properties>
    <finalName>toUpdate</finalName>
  </properties>
</project>

Note the two namespace declarations in the xsl:styleshhet start-tag. One is for addressing the elements in the source XML. The other puts any literal result elements in the stylesheet in the target namespace.


If you only to want to replace the text content of an element, without renaming it, you could simplify this to:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://maven.apache.org/POM/4.0.0"
exclude-result-prefixes="m">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="m:artifactId/text()">updated</xsl:template>

</xsl:stylesheet>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • I was close. I tried xmlns=... and xmlns:m=... but not both together, but I was doing all of it without proper understanding it. Thanks for explanation and simplified version just updating the content. Thank you! – Martin Mucha May 18 '20 at 19:36