2009-09-30 67 views
2

我是新來的XML和XSLT,並花了一些時間在什麼應該是一個非常簡單的搜索和替換的情況。我似乎無法得到正確的語法。基本的XML/XSLT變換:搜索和替換

本練習的總體目標是分別用'true'或'false'替換元素'NewCustomer'中'Y'和'N'的值。

這是我的示例數據。

<?xml version="1.0"?> 
<CustomerList> 
    <Customer> 
    <CustomerID>1111</CustomerID> 
    <CompanyName>Sean Chai</CompanyName> 
    <City>New York</City> 
    <NewCustomer>N</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1112</CustomerID> 
    <CompanyName>Tom Johnston</CompanyName> 
    <City>Los Angeles</City> 
    <NewCustomer>N</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1113</CustomerID> 
    <CompanyName>Institute of Art</CompanyName> 
    <City>Chicago</City> 
    <NewCustomer>Y</NewCustomer> 
    </Customer> 
</CustomerList> 

這是轉換樣式表。

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <!-- Identity Template (applies to all nodes and will copy all nodes --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Customer"> 
    <xsl:choose> 
     <xsl:when test="NewCustomer = 'Y'"> 
     <xsl:text>true</xsl:text> 
     </xsl:when> 
     <xsl:when test="NewCustomer = 'N'"> 
     <xsl:text>false</xsl:text> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

這是我的輸出。

<?xml version="1.0" encoding="utf-8" ?> 
    <CustomerList>false false true</CustomerList> 

這是我希望它輸出。

<?xml version="1.0"?> 
<CustomerList> 
    <Customer> 
    <CustomerID>1111</CustomerID> 
    <CompanyName>Sean Chai</CompanyName> 
    <City>New York</City> 
    <NewCustomer>false</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1112</CustomerID> 
    <CompanyName>Tom Johnston</CompanyName> 
    <City>Los Angeles</City> 
    <NewCustomer>false</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1113</CustomerID> 
    <CompanyName>Institute of Art</CompanyName> 
    <City>Chicago</City> 
    <NewCustomer>true</NewCustomer> 
    </Customer> 
</CustomerList> 

我在想什麼?爲什麼?我看到,如果我忽略檢查NewCustomer的子句,則會輸出整個輸出。但是,選擇爲NewCustomer輸出正確更改的值將僅顯示它們。是否有必須在第二個模板中引用之前的模板?

回答

3

通過讓您的模板與客戶匹配,您正在攔截該標籤的所有處理。

嘗試更改模板以僅匹配NewCustomer,從而在測試條件(test =「。='Y'」)中進行相應的更改。

另請注意,您必須在輸出中創建NewCustomer標記,因爲通過在自定義模板中匹配它,它不會被標識轉換處理。你非常接近。

下面是更新的模板:

<xsl:template match="Customer/NewCustomer"> 
    <xsl:copy> 
     <xsl:choose> 
      <xsl:when test=". = 'Y'"> 
       <xsl:text>true</xsl:text> 
      </xsl:when> 
      <xsl:when test=". = 'N'"> 
       <xsl:text>false</xsl:text> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:copy> 
</xsl:template> 

首先,它作爲NewCustomer客戶的孩子相匹配。然後,它使用xsl:copy複製節點(但不包括屬性或子節點)。然後它使用你的xsl:choose分別將N和Y值轉換爲false和true。

關鍵概念是,當模板匹配輸入元素時,輸入元素將被有效地從輸出中移除,並替換爲匹配模板的內容。在您與Customer進行匹配的情況下,Customer標籤及其內的所有內容都被替換爲剛剛生成'true'或'false'的模板內容。

+1

很好的解釋,+1。 – Tomalak 2009-10-01 10:51:08

+0

+1用於有效回答問題的原因部分。 – GuruM 2012-10-12 12:57:28

0

吉姆加里森的答案中的很好的解釋仍然適用。下面是一個冷凝/替代的方法:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:choose> 
     <xsl:when test="self::NewCustomer"> 
      <xsl:value-of select="boolean(number(translate(., 'YN', '10')))" /> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

表達boolean(number(translate(., 'YN', '10')))改變'Y''1''N''0',然後首先被轉換成數字,然後到一個布爾值。布爾值將分別表示爲'true''false'

這是一個有點髒,因爲它並沒有真正處理比'Y''N'其他值 - 但它會比'Y'以外的任何值輸出'false'

它只是一個節省空間。如果你願意,你可以用Jim Garrison所用的<xsl:choose>替換它。

4

吉姆加里森的將剝奪任何NewCustomer元素的屬性,他們。正如他所說的,托馬拉克有點骯髒。

這個版本是你的要求幾乎字面翻譯成XSLT:

<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="NewCustomer/text()[.='Y']"> 
    <xsl:text>true</xsl:text> 
    </xsl:template> 

<xsl:template match="NewCustomer/text()[.='N']"> 
    <xsl:text>false</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 

源代碼樹中的唯一節點,它不完全複製到結果集是是NewCustomer孩子文本節點元素,其值爲YN;對於那些,它分別發出truefalse

+0

+1確實有很多方法可以完成這項任務。我「假定」來自給定數據的模式,並且不打算複製屬性。 – 2009-10-02 04:56:19

+0

請參閱@JimGarrison回答問題的「如何/爲什麼」部分。 – GuruM 2012-10-12 13:00:10