2013-02-05 55 views
2

嘿,我需要使用XML 1.0將每個<a>標記中的內容修剪爲描述節點內的字符數限制20。下面是XML在HTML錨節點中修剪href

<description> 
     This is text <a href="http://stackoverflow.com/posts/14718323/edit">http://stackoverflow.com/posts/14718323/edit</a>. 
     Also here is more text than we have another 
     <a href="http://stackoverflow.com/posts/14718323/edit">http://stackoverflow.com/posts/14718323/edit</a>. 
    </description> 

我需要它變成是這樣的:

<description> 
     This is text <a href="http://stackoverflow.com/posts/14718323/edit">http://stacko</a>. 
     Also here is more text than we have another 
     <a href="http://stackoverflow.com/posts/14718323/edit">http://stacko</a>. 
    </description> 

我可以做大部分的邏輯,但我在做麻煩「的for-each」是搜索通過描述節點並轉換「每個」< a>。

這是否有意義?任何幫助讚賞。

**基於這裏提供的答案編輯13年2月7日*

是我在現在的位置。

<xsl:template match="/"> 
    <xsl:apply-templates select="//description"/> 
    </xsl:template> 

    <xsl:template match="a"> 
    <a href="{@href}"> 
     <xsl:value-of select="substring(normalize-space(),1,20)"/> 
    </a> 
    </xsl:template> 

的問題是「應用模板」不會起作用,因爲我有我的XSL多個模板。我需要專門調用一個模板,所以我認爲「呼叫模板」將成爲要走的路線。 「call-template」的唯一問題是我不知道如何指定一個特定的XML節點來引用。這裏是我到目前爲止已經破解它(deosn't工作):

<xsl:template match="/"> 
     <xsl:call-template name="trim_text"/> 
    </xsl:template> 

    <xsl:template name="trim_text" match="//description"> 
    <a href="{@href}"> 
     <xsl:value-of select="substring(normalize-space(),1,20)"/> 
    </a> 
    </xsl:template> 

最初的「調用模板」需要在一個<xsl:template match="/">,因爲這是一個更大的功能去。所以,我需要三樣東西:

1)HREF留什麼在XML

2)<a>標籤之間的文本被修剪爲20px

3)我需要調用一致這個模板來自一個更大的xsl模板,它在XML上做了很多轉換。這將是大約7個模板調用。

+0

concatenate?輸出需要什麼樣子? – Vinit

+0

我的歉意。基本上我需要將< a >標記中的字符限制爲20像素。因此,例如...「http://www.longlink/morelink/page/anotherpage」將不得不縮短爲「http://www.longlink/mor」 – DigitalMC

+1

我認爲你的意思是「修剪」而不是連接 – Vinit

回答

1

的問題是「應用模板」不會起作用,因爲我有我的XSL多個模板。我需要專門調用一個模板,所以我認爲「呼叫模板」將成爲要走的路線。 「call-template」的唯一問題是我不知道如何指定一個特定的XML節點來引用。

模板模式可能是你在找什麼

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

    <xsl:template match="/"> 
    <!-- do some other stuff ... --> 

    <!-- handle the description --> 
    <xsl:apply-templates select=".//description" mode="description" /> 

    <!-- more other stuff here --> 
    </xsl:template> 

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

    <xsl:template match="a" mode="description"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*" mode="description" /> 
     <xsl:value-of select="substring(., 1, 20)" /> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

當你apply-templates指定的模式,只標有同樣的方式找到適用於模板時,會考慮模板每個節點(加上與所有元素節點相匹配的默認隱式模板,並使用相同模式遞歸地將模板應用於兒童,但這不適用,因爲我們有一個身份模板)。這爲a元素例如模板不允許包含其他標籤鏈接,例如

<a href="#">This is a <b>very</b> long piece of text used as an example</a> 

將成爲

<a href="#">This is a very long </a> 

如果你想保持這種標記它變得更加複雜。你不能用

<xsl:template match="a//text()" mode="description"> 
    <xsl:value-of select="substring(., 1, 20)"/> 
</xsl:template> 

顯而易見的方法做到這一點,因爲這會對待每一個孤立文本節點,併產生

<a href="#">This is a <b>very</b> long piece of text </a> 

(如「這是一個」和「非常」已經短於20個字符,而「長文本」是截斷爲「用作...的長文本」的20個字符)

+0

這個作品很棒!非常感謝。我非常欣賞這些描述,使一切都變得清晰。我有一個問題是「@ * | node()」是什麼意思?這是我唯一困惑的事情。 – DigitalMC

+0

所以我只是意識到XML被包裝在CDATA中,所以我的輸出是''而不是''你知道任何方式嗎?在這附近? – DigitalMC

+0

@ user2001026匹配'@ * | node()'的模板是XSLT的_identity template_ - 它將其輸入複製爲逐字輸出。 '@ *'匹配任何屬性節點,'node()'匹配任何元素,文本節點,註釋或處理指令。模板在輸出中創建匹配節點的副本,然後遞歸地將模板應用於任何子節點。任何涉及對輸入XML進行小調整的XSLT任務通常都可以通過使用標識模板,然後有選擇地覆蓋它(與我的模板匹配'a'元素)來解決任何您想要處理的問題。 –

1

回答OP在評論中修改的問題,他需要將字符限制爲20個字符。

嘗試的子功能只返回前20個字符:

<xsl:value-of select="substring(.,1,20)"/> 

下面是一個更完整的答案:

這XSLT 1。0變換:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
     <xsl:template match="@*|node()"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*|node()"/> 
      </xsl:copy> 
     </xsl:template> 
     <xsl:template match="a/@href"> 
      <xsl:attribute name="href"><xsl:value-of select="substring(.,1,20)"/></xsl:attribute> 
     </xsl:template> 
    </xsl:stylesheet> 

當施加到這個XML文檔:

<root> 
     <description> 
      This is text <a href="http://www.longlink/morelink/page/anotherpage">Link Here</a>. 
      Also here is more text than we have another 
      <a href="link-style:null">Link Here</a>. 
     </description> 
    </root> 

在所希望的結果的結果(注意第一href屬性的縮短):

<root> 
     <description> 
      This is text <a href="http://www.longlink/">Link Here</a>. 
      Also here is more text than we have another 
      <a href="link-style:null">Link Here</a>. 
     </description> 
    </root> 

說明:

  • 身份變換(第一模板)將複製所有的節點和屬性到結果樹,
  • 第二個模板將只複製的HREF
  • 前20個字符還要注意缺乏for-each,而是使用模板規則和apply-templates。你可以在哪裏,你應該使用模板。
+0

感謝您的幫助! – DigitalMC

2

這種轉變避免使用xsl:attribute,是更好的格式化,更可讀

<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="a[@href]"> 
    <a href="{substring(@href,1,20)}"> 
    <xsl:apply-templates select="@*[not(name()='href')]|node()"/> 
    </a> 
</xsl:template> 
</xsl:stylesheet> 

當此XML文檔的應用:

<root> 
    <description> 
      This is text 
     <a href="http://www.longlink/morelink/page/anotherpage">Link Here</a>. 
      Also here is more text than we have another 
     <a href="link-style:null">Link Here</a>. 
    </description> 
</root> 

產生通緝,正確的結果:

<root> 
    <description> 
      This is text 
     <a href="http://www.longlink/">Link Here</a>. 
      Also here is more text than we have another 
     <a href="link-style:null">Link Here</a>. 
    </description> 
</root> 

說明

  1. Identity rule - 複製爲是指此模板被選擇用於執行每個節點。

  2. 使用AVT(屬性值模板)。

+0

這看起來很不錯,但對於href來說很好,但問題是我需要標記內的文字縮短,而不是href。這個代碼可以調整來完成這個嗎? – DigitalMC

+1

當然,使用: ' –

+0

這真是太棒了,感謝!我現在唯一遇到的問題是「apply-templates」是否正確地應用了XSL文檔中的所有模板?那麼我有一堆XSL模板(大約7)。我只想應用一個模板來修剪上述鏈接。我將把它存儲在一個變量中,並在稍後輸出。你能用這個代碼使用「call-tempalte」嗎?它不斷爲我打破。 – DigitalMC