2012-03-05 63 views
2

我正在尋找一種更簡單,更優雅的方式來替換XML中的文本。對於一個XML源,如:簡單的XSLT文本替換

<A> 
<B> 
    <Name>ThisOne</Name> 
    <Target>abc</Target> 
</B> 
<B> 
    <Name>NotThisOne</Name> 
    <Target>abc</Target> 
</B> 
<B> 
    <Name>ThisOne</Name> 
    <Target>def</Target> 
</B> 
</A> 

我想改變這種具有「ThisOne」到「XYZ」的名稱所有目標元素的文本。

其結果將是:

<A> 
<B> 
    <Name>ThisOne</Name> 
    <Target>xyz</Target>  <-- Changed. 
</B> 
<B> 
    <Name>NotThisOne</Name> 
    <Target>abc</Target> 
</B> 
<B> 
    <Name>ThisOne</Name> 
    <Target>xyz</Target>  <-- Changed. 
</B> 
</A> 

我完成了這一具有:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="B/Target"> 
    <xsl:choose> 
     <xsl:when test="../Name/text()='ThisOne'"><Target>xyz</Target></xsl:when> 
     <xsl:otherwise><Target><xsl:value-of select="text()"/></Target></xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

我想這可能是與< XSL來完成:模板匹配=「B /目標/文() 「>,所以我可以只替換文本而不是整個元素,但我無法弄清楚其餘部分。

在此先感謝。

+0

有趣 - 在幾分鐘內有3個非常相似的答案 - 我真的很歡迎來自這裏真正的專家之一的文體比較和對比。 *特別是*如果它指出了我的解決方案的改進 – Kevan 2012-03-05 19:38:38

+1

@凱文 - 您的答案唯一的問題是,如果''元素包含任何屬性,它們將被剝離。 – 2012-03-05 19:58:39

+0

@DevNull - 好點 - 你的/文本()風格是不太可能表現出意外的行爲是輸入文件改變,並開始在目標元素上的屬性 - 我很高興我問:) – Kevan 2012-03-05 20:03:32

回答

5

這個樣式表:

<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:template match="B[Name='ThisOne']/Target/text()"> 
    <xsl:text>xyz</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 

使用XML輸入產生:

<A> 
    <B> 
    <Name>ThisOne</Name> 
    <Target>xyz</Target> 
    </B> 
    <B> 
    <Name>NotThisOne</Name> 
    <Target>abc</Target> 
    </B> 
    <B> 
    <Name>ThisOne</Name> 
    <Target>xyz</Target> 
    </B> 
</A> 
+0

非常好,謝謝! – uncaged 2012-03-05 20:18:18

+0

+1爲一個很好的答案。 – 2012-03-06 02:55:04

+0

+1,用於優秀的XSLT代碼。 – 2014-11-13 16:44:21

1

這是所有你需要做的:

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

<xsl:template match="B/Target[../Name='ThisOne']"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <xsl:text>xyz</xsl:text> 
    </xsl:copy> 
</xsl:template> 

第一個模板是「恆等變換「並將輸入複製到輸出不變。第二個匹配您想要更改的特定目標,複製標籤和屬性,並替換所需的文本。

+0

不錯,謝謝! – uncaged 2012-03-05 20:18:06

1
<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cds="cds_dt" exclude-result-prefixes="cds"> 
    <!-- Identity transfrom - just copy what doesn't need changing --> 
    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- a rule for what does need changing --> 
    <!-- Change all Target nodes whose parent has a child of Name equal to ThisOne --> 
    <xsl:template match="/A/B[Name='ThisOne']/Target"> 
     <Target>xyz</Target> 
    </xsl:template> 
</xsl:stylesheet> 
+0

謝謝。這當然是更清潔的,但不排除必須替換整個元素,而不是僅僅取代文本。 – uncaged 2012-03-05 19:56:27