2012-02-28 68 views
2

我在PHP开工项目,使用XML,现在我需要申请改造,使我发现首次XSL ...XSL添加属性家长基于孩子

我所面临的问题:如何建立XSL做如下改造: - 以“attrib-”开始转变为属性的父节点的节点

例子:

<a1> 
    <b1> 
    <attrib-c1>12</attrib-c1> 
    <c2>23</c2> 
    </b1> 
</a1> 

应该变成:

<a1> 
    <b1 c1="12"> 
    <c2>23</c2> 
    </b1> 
</a1> 

我已经开始解决方案是这样的:

<xsl:stylesheet> 
    <xsl:output method="xml"/> 
    <xsl:template match="@*|*|text()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|*|text()"/> 
    </xsl:copy> 
    </xsl:template> 
... 
</xsl:stylesheet> 

我需要一些帮助来解决这个任务。由于事先...

+0

所以你所做的只是复制一个身份转换。你是否试图解决这个问题?这是功课吗? – 2012-02-28 20:47:02

回答

1

这几乎是相同的溶液作为DevNull的,但在万一有一个现有的属性,并通过一个子元素定义了新的一者之间的冲突,后者取代了以前

<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="*"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <xsl:apply-templates mode="attr" select="*[starts-with(name(), 'attrib-')]"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template mode="attr" match="*[starts-with(name(), 'attrib-')]"> 
    <xsl:attribute name="{substring-after(name(), 'attrib-')}"> 
    <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 

<xsl:template match="*[starts-with(name(), 'attrib-')]"/> 
</xsl:stylesheet> 

当这种转变被应用在下面的XML文档

<a1> 
    <b1 existing="attr" x="Y"> 
    <attrib-new>12</attrib-new> 
    <c2>23</c2> 
    <attrib-new2>ABCD</attrib-new2> 
    <attrib-x>Z</attrib-x> 
    </b1> 
</a1> 

想要的,正确的结果产生

<a1> 
    <b1 existing="attr" x="Z" new="12" new2="ABCD"> 
     <c2>23</c2> 
    </b1> 
</a1> 
+0

+1善于处理潜在的冲突。 – 2012-02-28 21:38:31

+0

伟大的解决方案。谢谢! – 2012-02-28 22:11:46

+0

@ZoranKalinić:不客气。 – 2012-02-28 22:48:55

3

XML输入(改性,以略微增加的复杂度。)

<a1> 
    <b1 existing="attr"> 
    <attrib-c1>12</attrib-c1> 
    <c2>23</c2> 
    <attrib-dh>DevNull</attrib-dh> 
    </b1> 
</a1> 

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[starts-with(name(),'attrib')]" mode="attr"/> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*[starts-with(name(),'attrib')]"/> 

    <xsl:template match="*" mode="attr"> 
    <xsl:attribute name="{substring-after(name(),'-')}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 

XML输出

<a1> 
    <b1 c1="12" dh="DevNull" existing="attr"> 
     <c2>23</c2> 
    </b1> 
</a1> 
+0

+1很好的答案。另外,''可以替换为'',对吧?你也可以将''改为'”,因为只有以'attrib-'开头的元素才会在该模式下处理。 – LarsH 2012-02-28 21:26:08

+0

@LarsH - 谢谢,这些都是很棒的建议。不知道为什么我没有使用'xsl:copy';这就是我得到的冲动。 – 2012-02-28 21:35:13

+2

+1一个很好的答案。似乎拉尔斯忘记了实际上的赞成。 – 2012-02-28 21:42:37

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

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <!-- match elements with children like attrib- and copy/pass --> 
    <xsl:template match="*[*[starts-with(name(.),'attrib')]]"> 
     <xsl:copy> 
     <xsl:apply-templates select="*[starts-with(name(.),'attrib')]"/> 
     <xsl:apply-templates select="@*|*[not(starts-with(name(.),'attrib'))]"/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- match elements like attrib- and output them as attribute --> 
    <xsl:template match="*[starts-with(name(.),'attrib')]"> 
     <xsl:attribute name="{substring-after(name(.),'attrib-')}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
+1

很高兴见到你回到了stackoverflow! +1对于一个好的答案 – 2012-02-28 21:39:20

+0

好,但要小心''' 。这不能复制元素以外的子元素(例如文本节点,注释等)。 – LarsH 2012-02-28 21:52:20

+0

感谢您的回答! – 2012-02-28 22:12:26