XSLT转换:根据其属性值展平嵌套节点

时间:2014-04-06 11:24:29

标签: xml xslt

我想使用XSLT压缩XML文件。示例(可能有任意数量的nodeedge节点):

输入:

<?xml version="1.0" encoding="utf-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns">
  <graph>

    <node id="0">
      <data key="label">A</data>
      <data key="tag1">0</data>
      <data key="tag2">0</data>
    </node>

    <edge id="0" source="0" target="1">
      <data key="label">REFERENCED_TO</data>
    </edge>

  </graph>
</graphml>

期望的输出:

<?xml version="1.0" encoding="utf-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns">
  <graph>

    <node id="0" label="A">          
      <data key="tag1">0</data>
      <data key="tag2">0</data>
    </node>

    <edge id="0" source="1" target="0" label="REFERENCED_TO"/>

  </graph>
</graphml>

如何仅展开data属性设置为key的{​​{1}}代码?

3 个答案:

答案 0 :(得分:3)

  

如何仅展平设置了键属性的数据标记   “标记”?

怎么样:

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<!-- add label attribute -->
<xsl:template match="gml:node | gml:edge">
    <xsl:copy>
        <xsl:if test="gml:data[@key='label']">
            <xsl:attribute name="label"><xsl:value-of select="gml:data[@key='label']"/></xsl:attribute>
        </xsl:if>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- suppress label element -->
<xsl:template match="gml:data[@key='label']"/>

</xsl:stylesheet>

答案 1 :(得分:1)

有一些空余时间,我想出了以下XSLT(基于1.0的基础非常详细)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                xmlns:g="http://graphml.graphdrawing.org/xmlns"
                exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="*[*/@key='label']">
      <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
        <xsl:copy-of select="@*"/>
      <xsl:attribute name="label">
        <xsl:value-of select="*[@key='label']/text()" />
      </xsl:attribute>
      <xsl:apply-templates select="*[not(@key='label')]"/>
      </xsl:element>
    </xsl:template>

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

</xsl:stylesheet>

希望这有帮助,

答案 2 :(得分:1)

来自hor257k的解决方案似乎包含三个@ key ='label'测试,其中一个会做。这是尝试改进它:

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<!-- convert label element to attribute -->
<xsl:template match="gml:data[@key='label']">
  <xsl:attribute name="label">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

并且为了完整性,这是XSLT 3.0版本:

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>

<!-- convert label element to attribute -->
<xsl:template match="gml:data[@key='label']">
  <xsl:attribute name="label" select="."/>
</xsl:template>

</xsl:stylesheet>