Xml XSL节点交换不起作用

Xml XSL节点交换不起作用,xml,xslt,xslt-2.0,Xml,Xslt,Xslt 2.0,我试图编写一个XSL来整理一些特定的XML文件,这些文件是Maven的POM。我想做的是重新排列某些顶级元素的顺序,删除一个元素,然后像复制所有其他元素一样进行复制。原始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/PO

我试图编写一个XSL来整理一些特定的XML文件,这些文件是Maven的POM。我想做的是重新排列某些顶级元素的顺序,删除一个元素,然后像复制所有其他元素一样进行复制。原始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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.sourceforge.ondex.apps</groupId>
    <name>Ondex</name>
    <version>0.6.0-SNAPSHOT</version>
    <artifactId>installer</artifactId>
    <packaging>pom</packaging>
    <description>NSIS based Installer</description>
    <parent>
        <artifactId>apps</artifactId>
        <groupId>net.sourceforge.ondex</groupId>
        <version>0.6.0-SNAPSHOT</version>
    </parent>
    <organization>
        <name>Ondex Project</name>
        <url>http://www.ondex.org</url>
    </organization>

    <build>
    ...
    </build>
  ...
</project>
此XML几乎与Saxon HE-9-7-06J配合使用:

<?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:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math pom"
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:pom="http://maven.apache.org/POM/4.0.0"
    >
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/pom:project">
        <project>
            <xsl:copy-of select="@*" />
            <xsl:apply-templates select="pom:modelVersion" />
            <xsl:apply-templates select="pom:parent" />     
            <xsl:apply-templates select="pom:groupId" />
            <xsl:apply-templates select="pom:artifactId" />
            <xsl:apply-templates select="pom:name" />
            <xsl:apply-templates select="pom:description" />
            <xsl:apply-templates
                select="node() except (pom:modelVersion|pom:parent|pom:groupId|pom:artifactId|pom:name|pom:description|pom:version)" />
        </project>
    </xsl:template>

    <!-- And the usual identity transform for all other nodes --> 
    <xsl:template match="node()|@*">
        <xsl:copy><xsl:apply-templates select="node()|@*" /></xsl:copy>
    </xsl:template>

</xsl:stylesheet>
但是,输出中添加了不需要的空行来代替移动的节点,例如,请参见描述后的行,其中最初我有父节点:

<?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/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
            <artifactId>apps</artifactId>
            <groupId>net.sourceforge.ondex</groupId>
            <version>0.6.0-SNAPSHOT</version>
      </parent>
   <groupId>net.sourceforge.ondex.apps</groupId>
   <artifactId>installer</artifactId>
   <name>Ondex</name>
   <description>NSIS based Installer</description>





      <packaging>pom</packaging>


      <organization>
            <name>Ondex Project</name>
            <url>http://www.ondex.org</url>
      </organization>

      <build>
      ...
      </build>
  ...
</project>
我做错了什么?请注意,我不想使用xsl:strip space,因为我想保留放在原始文件中的空间以便于可读。

使用*选择节点而不是节点:


使用XSLT 2.0代码

好的,在您在此友好地写下答案和评论之后,我意识到发生了什么,并找到了解决方法:

@michael.hor257k解释说,问题在于匹配元素之间的换行,例如,由XSL作为节点匹配,并单独在输出中报告,导致空行

单靠它是不够的,因为它会删除这些新行以及手动插入的空行,我想保留它们

但这是一个良好的开端:我使用以下方法预处理XML:

sed -E s/'^\s*$'/'<white-line\/>'/ pom.xml  | sponge pom.xml
也就是说,所有“真实”的白线都被标记替换。因此,除了以下内容之外,现在可以很容易地将其添加到上面的XSL中:

您可能还需要这样做,以避免它们在根元素之外被自定义XML填充,从而导致错误


谢谢你的帮助

那么XSLT应该如何识别要删除的空间,并将这些空间保留在原始文件中以便于阅读呢?您的上一页未尝试排除任何空白文本。没有要删除的空格。XSLT正在移动捕获的元素的位置添加空行,例如,代替父元素。@zakmck我恐怕你误解了这里发生的事情。转换不会添加任何空行。它从输入XML复制它们。您将发现很难将位于和之间的空白文本节点与位于和之间的空白文本节点区别对待。也许你可以通过计算它们包含多少换行符来区分它们?@MartinHonnen,我想你是对的,我会尝试匹配并忽略我移动的标记之间的空格,看看我能做些什么。谢谢。不幸的是,这也会删除原始文件中的空行。为了更好地解释它:被移动到输出中的正确位置,但我在它最初所在的位置看到了空行。相反,原始XML中的任何其他空行都会正确地报告在输出中,这正是我想要的。在这种情况下,我建议使用剥离所有空格,并在任何需要的地方添加新行,以便于可读。无法工作,抱歉。我想报告用户在原始XML中放入的空格,显然我不知道放在哪里。问题是XSLT正在添加更多的功能。我想我已经理解了为什么:节点匹配新的行?在一个元素的关闭和下一个元素的打开之间,但我不知道如何摆脱它。
sed -E s/'^\s*$'/'<white-line\/>'/ pom.xml  | sponge pom.xml
<xsl:template match="pom:white-line">
  <xsl:text>

  </xsl:text>
</xsl:template>