2010-04-19 45 views
0

我想要一個XML樣式表(XSLT),它將一對一地放置少數特定子節點的屬性。這是什麼XSLT?什麼是XSLT一對一編寫某些節點屬性?

我最近問了一個related question,有人提供了一個樣式表來解決,但他們的樣式表由於某種原因沒有工作,我很好奇爲什麼 - 這些屬性並沒有結束每一行。

舉例來說,我的XML可能是這樣的:

<MyXML> 
    <NodeA> 
     <ChildNode value1='5' value2='6' /> 
    </NodeA> 
    <NodeB> 
     <AnotherChildNode value1='5' value2='6' /> 
    </NodeB> 
    <NodeC> 
     <AnotherChildNode value1='5' value2='6' /> 
    </NodeC> 
</MyXML> 

而且我希望有一個樣式表,將擴大所有NodeA上的和NodeB的,但不是NodeCs,使它看起來像這樣:

<MyXML> 
    <NodeA> 
     <ChildNode 
      value1='5' 
      value2='6' /> 
    </NodeA> 
    <NodeB> 
     <AnotherChildNode 
      value1='5' 
      value2='6' /> 
    </NodeB> 
    <NodeC> 
     <AnotherChildNode value1='5' value2='6' /> 
    </NodeC> 
</MyXML> 

回答

1

我會說XSLT不適合這份工作。

XSLT的目標是將數據從一種格式轉換爲另一種格式。

你可以實現爲「漂亮打印」輸出換行符,但你應該記住,這總是一種「黑客」。

是否有使用XSLT而不是$ PreferedScriptingLanguage的原因?

+2

技術上,XSLT的目標是把輸入樹到輸出樹。如何將該樹序列化爲文檔基本上超出了XSLT規範的範圍。 – fpmurphy1 2010-04-19 15:26:12

+0

@echox:我的印象是XSLT並不在乎它寫出來的是什麼,只要它輸入XML即可。你不能從XSLT中吐出任意文本嗎? – 2010-04-21 14:30:39

+0

當然可以,但是你也可以用鞋子在牆上打釘子。對不起,現在沒有想到更好的比喻;-) 您可以實現這一點,但它會導致非常醜陋,無法讀取的代碼,這是任何人都不希望維護的(請參閱@tomalak的解決方案)。 XSLT規範在第一句中說:「[..]它是將XML文檔轉換爲其他XML文檔的語言。」 http://www.w3.org/TR/1999/REC-xslt-19991116 – echox 2010-04-21 21:17:22

1

XML明智,這些是完全相同的。所以用XSLT轉換它們不會改變它們。

所以你可以嘗試

  1. 濫用一些XSLT處理器(具有標識XSLT轉換)作爲一個「漂亮」的打印機。

  2. 獲取或寫一個特別漂亮的打印機。

  3. 讓XML保持原樣,然後調整處理鏈中的下一步,以解析XML而不是解析行中的值。

我贊成3

+0

對於#1,請參閱我的答案。我個人投票支持這個,我也會支持#3。 – Tomalak 2010-04-19 15:27:52

+0

@ndim:我不是在寫一個XML解析器(我不是瘋了!)。這是一個人類可讀性問題。我們已經交給的XML格式在幾個關鍵節點上使用了25-100個屬性來進行配置設置,而且它不可讀,winmerge幾乎不能兼容,而且很難編輯。當它是一對一時,人類可以更容易管理。 我的理解是,XSLT不要求OUTPUT是XML,那是錯的嗎?從維基百科(儘管它對我有點混亂)「新文檔可能會被處理器以標準XML語法或其他格式(如HTML或純文本)序列化(輸出)。」 – 2010-04-19 17:13:01

+0

您不需要編寫解析器(任何現有的解析器都應該這樣做) - 您需要編寫一個序列化器。因此,如果您使用標準的SAX解析器,編寫一些代碼來跟蹤當前上下文以確定您在文檔中的位置,然後調整標準序列化程序以插入一些換行符......應該可以工作。然而,我會爭辯說,對於一個對人類而言仍然難以辨認的元素有100個attrs。 – ndim 2010-04-22 11:12:38

1

嗯......如果(且僅當)輸入XML已經縮進正確,你可以用這個脫身:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:output encoding="utf-8" /> 

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

    <xsl:template match="NodeA/*|NodeB/*"> 
    <xsl:variable name="spc" select="preceding-sibling::text()[1]" /> 
    <xsl:value-of select="concat('&lt;', name())" disable-output-escaping="yes" /> 
    <xsl:for-each select="@*"> 
     <xsl:value-of select="concat($spc, ' ', name(), '=&quot;', ., '&quot;')" /> 
    </xsl:for-each> 
    <xsl:choose> 
     <xsl:when test="node()"> 
     <xsl:value-of select="'&gt;'" disable-output-escaping="yes" /> 
     <xsl:apply-templates select="node()" /> 
     <xsl:value-of select="concat('&lt;/', name(), '&gt;')" disable-output-escaping="yes" /> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="' /&gt;'" disable-output-escaping="yes" /> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

但要說實話,我認爲這正是@echox談論的那個醜陋的黑客。

輸出OUF上面的將是:

<MyXML> 
    <NodeA> 
     <ChildNode 
      value1="5" 
      value2="6" /> 
    </NodeA> 
    <NodeB> 
     <AnotherChildNode 
      value1="5" 
      value2="6" /> 
    </NodeB> 
    <NodeC> 
     <AnotherChildNode value1="5" value2="6"></AnotherChildNode> 
    </NodeC> 
</MyXML> 
+0

upvote for special brainfuck solution :-D – echox 2010-04-19 15:43:40

+0

@echox:我做了很多XSLT問題,所以我對它有一定的寬容度)。不過,這樣的事情讓我的眼睛流血。儘管如此,這是幾天前我做的類似的:http://stackoverflow.com/questions/2638367/how-do-i-emit-escaped-xml-representation-of-a-node-in-my-xslts -html-output/2652733#2652733 :-D – Tomalak 2010-04-19 15:49:47