2017-01-25 52 views
0

我想寫一個XSL來整理一些特定的XML文件(它們是Maven的POM)。我想要做的是重新排列某些頂級元素的順序,刪除一個元素並按原樣複製所有其他元素。原始的XML的一個例子是:XSL節點交換不起作用

<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幾乎工作(與撒克遜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,因爲我想保留爲了便於閱讀而放在原始文件中的空格。

+0

那麼XSLT應該如何識別要刪除的空間並將這些「爲了便於閱讀而放在原始文件中」?您的最後一個'

+0

沒有可刪除的空間。 XSLT在捕捉到的元素被移動的位置添加空行(例如,代替父元素)。 – zakmck

+2

@ zakmck恐怕你誤解了這裏發生的事情。轉換不會添加任何空白行。它從輸入XML複製它們。你會發現很難將位於''和'之間的空白文本節點視爲位於''和''之間的空白文本節點。也許你可以通過計算它們包含的換行字符數來區分它們。 –

回答

0

OK,問題的答案後,你評論好心寫到這裏,我已經意識到發生了什麼事情,並發現了一個解決辦法:

正如@ michael.hor257k解釋說,這個問題是匹配的元素(例如,</parent><organization>)由XSL爲節點匹配,並報告之間的換行符僅在輸出中,導致空行。

<xsl:strip-space>單是不夠的,導致它與手動插入的空行一起刪除這些換行符,我想保留它們。

但它是一個良好的開端:我預處理XML具有:

sed -E s/'^\s*$'/'<white-line\/>'/ pom.xml | sponge pom.xml 

也就是說,所有「真正的」白線由標籤<white-line />取代。所以,現在很容易這上面除了添加到XSL來<xsl:strip-space elements="*" />

<xsl:template match="pom:white-line"> 
    <xsl:text> 

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

可能的話,你可能還需要remove starting/trailing blank lines,以避免他們充滿了自定義XML根元素之外,從而導致錯誤。

感謝您的幫助!

0

使用*選擇的節點,而不是node()

<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="* 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> 

工作XSLT 2.0代碼here

+0

不幸的是,這也刪除了原始文件中的空白行。爲了更好地解釋它:被移動到輸出中的正確位置,但我在最初位置的位置看到空行。相反,原始XML中的任何其他空白行都會在輸出中正確報告,這正是我想要的。 – zakmck

+0

在這種情況下,我會建議使用''去除所有空格,並在需要時使用''來添加新行。 – Madeyedexter

+0

無法工作,對不起。我想報告用戶在原始XML中放置的空間(顯然,我不知道它在哪裏)。問題是XSLT增加了更多。我認爲我沒有理解爲什麼:node()在元素的閉包和下一個元素的打開之間匹配一些東西(換行符),但是我不明白什麼以及如何擺脫它。 – zakmck