【问题标题】:updating pom.xml elements using xslt使用 xslt 更新 pom.xml 元素
【发布时间】:2020-05-19 01:01:58
【问题描述】:

我正在尝试使用 xslt 更新 pom.xml 中的 finalName、artifactId 和 name。我不了解 xslt 转换,但我发现了这个:how to modify xml file using xslt 这似乎很容易理解,因此我创建了这个模板:

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

并使用以下方法构建它:

xsltproc template.xsl pom.xml &gt; modified-pom.xml

但是由于某些我不知道的原因,xpath //artifactId 似乎没有被匹配和替换。我也尝试过:仅artifactIdproject/artifactId/project/artifactId 等,但没有匹配项。记住使用需要特定命名空间的xmlstalet 的教训,这似乎可能与命名空间有关,但我真的不知道如何修复它,因为 man xsltproc 似乎以某种方式被破坏/不反映命令现实。谁能帮忙看看哪里出错了?

编辑:根据评论请求添加了部分解决的状态:

作为一个最小工作示例输入文件,我们可以考虑这个 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>

我现在正在使用模板:

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

并使用命令替换它:xsltproc template.xsl min.xml &gt; out.xml

输出是:

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

我想删除部分xmlns="" xmlns:m="http://maven.apache.org/POM/4.0.0"

如果我将模板中的替换更新为:&lt;m:finalName&gt;updated&lt;/m:finalName&gt; 我没有得到正确的结果,而是:

&lt;m:finalName xmlns:m="http://maven.apache.org/POM/4.0.0"&gt;updated&lt;/m:finalName&gt;

尝试声明全局命名空间而不是 m 也没有帮助我,因为它甚至没有构建。

预期的输出是输入,toUpdate 替换为 updated

【问题讨论】:

  • 我认为 POM 文件使用命名空间,所以这可能是所有关于如何使用默认命名空间声明选择和匹配 XML 文件中的元素的问题的重复。
  • @MartinHonnen 你是对的,没能找到它。谢谢你的帮助。我会添加有效的模板作为答案,除非你尽快这样做——但似乎你不需要额外的业力;)无论如何,谢谢你帮助我!
  • @MartinHonnen ...但是,当我声明xmlns:os 并相应地更新匹配以说os:/project/os:artifactId 它可以工作甚至构建,但生成的元素是&lt;artifactId xmlns="" xmlns:os="http://maven.apache.org/POM/4.0.0"&gt;actualValue&lt;/artifactId&gt; 有没有办法获得在每个更改的元素中去掉那个 xmlns 声明?
  • @MartinMucha 如果您希望新元素与其替换的元素位于同一名称空间中,则必须将其放在此处。您在问题中显示的内容会在无命名空间中创建一个元素,并且已正确标记为这样。如果您无法解决此问题,请发布 minimal reproducible example 显示输入、XSLT 和预期输出。
  • 已添加,很抱歉没有提供足够的信息。

标签: xslt


【解决方案1】:

考虑以下最小化的示例:

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>

结果

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

注意xsl:styleshhet 开始标记中的两个命名空间声明。一种是用于寻址源 XML 中的元素。另一个将任何文字结果元素放在目标命名空间的样式表中。


如果您只想替换元素的文本内容而不重命名它,您可以将其简化为:

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

【讨论】:

  • 我很接近。我尝试了 xmlns=... 和 xmlns:m=... 但没有同时尝试,但是我在没有正确理解的情况下完成了所有这些操作。感谢您的解释和简化版本只是更新了内容。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多