XSLT通过属性转换为树XML结构

时间:2015-07-21 16:36:34

标签: xml xslt

我有一些XML文件具有以下扁平结构:

<managedObject class="MGW" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454" id="192614000001726941">
  <list name="mgwOptions">
    <p>M3UA Interface (No 50035)</p>
  </list>
  <p name="name">MGW_A</p>
</managedObject>
<managedObject class="ATM" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454/ATM-1" id="192614000003145148">
  <p name="lastSuccessfulUploadTimeStamp">21/07/15 01:32:40</p>
</managedObject>
<managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-0" id="192614000003415034">
  <p name="prSectionSdhExchangeTerminalIndex">1</p>
  <p name="protectionSwitchingMode">REV</p>
  <p name="protocolVariant">MSP</p>
  <p name="switchingDirection">WO</p>
  <p name="waitToRestoreTime">300</p>
  <p name="woSectionSdhExchangeTerminalIndex">0</p>
</managedObject>
<managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-1" id="192614000003415035">
  <p name="prSectionSdhExchangeTerminalIndex">3</p>
  <p name="protectionSwitchingMode">REV</p>
  <p name="protocolVariant">MSP</p>
  <p name="switchingDirection">WO</p>
  <p name="waitToRestoreTime">300</p>
  <p name="woSectionSdhExchangeTerminalIndex">2</p>
</managedObject>

我想根据 managedObjects 元素的 distName class 属性,在更加树状的结构中使用XSL进行转换。类似的东西:

<?xml version="1.0"?>
<managedObject class="MGW" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454" id="192614000001726941">
  <list name="mgwOptions">
    <p>M3UA Interface (No 50035)</p>
  </list>
  <p name="name">MGW_A</p>
  <managedObject class="ATM" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454/ATM-1" id="192614000003145148">
    <p name="lastSuccessfulUploadTimeStamp">21/07/15 01:32:40</p>
    <managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-0" id="192614000003415034">
      <p name="prSectionSdhExchangeTerminalIndex">1</p>
      <p name="protectionSwitchingMode">REV</p>
      <p name="protocolVariant">MSP</p>
      <p name="switchingDirection">WO</p>
      <p name="waitToRestoreTime">300</p>
      <p name="woSectionSdhExchangeTerminalIndex">0</p>
    </managedObject>
    <managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-1" id="192614000003415035">
      <p name="prSectionSdhExchangeTerminalIndex">3</p>
      <p name="protectionSwitchingMode">REV</p>
      <p name="protocolVariant">MSP</p>
      <p name="switchingDirection">WO</p>
      <p name="waitToRestoreTime">300</p>
      <p name="woSectionSdhExchangeTerminalIndex">2</p>
    </managedObject>
  </managedObject>
</managedObject>

类似的东西是如此简单易懂吗?我的文件包含大约100,000个托管对象,这些对象具有不同的类和不同的distName路径。

1 个答案:

答案 0 :(得分:2)

更好的解释会很有用。盯着这个例子,我看不出class属性在这里扮演什么角色;通过将最后distName之前的/子字符串与父级的整个distName字符串进行比较,似乎将子项链接到其父级。

除了使用上述规则寻找孤儿外,还没有明显的方法可以确定“祖先”是谁。

另请注意,您的输入不是格式良好的XML:您必须具有单个根元素。

现在,如果您可以使用XSLT 2.0,请尝试:

XSLT 2.0

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:function name="my:substring-before-last">
    <xsl:param name="string"/> 
    <xsl:param name="delimiter"/> 
    <xsl:value-of select="tokenize($string, $delimiter)[position()!=last()]" separator="{$delimiter}"/>
</xsl:function>

<xsl:key name="child" match="managedObject" use="my:substring-before-last(@distName, '/')" />
<xsl:key name="parent" match="managedObject" use="@distName" />

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

<xsl:template match="/input">
    <output>
        <!-- select progenitors -->
        <xsl:apply-templates select="managedObject[not(key('parent', my:substring-before-last(@distName, '/')))]" />
    </output>
</xsl:template>

<xsl:template match="managedObject">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <!-- select children -->
        <xsl:apply-templates select="key('child', @distName)"/> 
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

应用于以下格式良好的输入:

<强> XML

<input>
    <managedObject class="MGW" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454" id="192614000001726941">
      <list name="mgwOptions">
        <p>M3UA Interface (No 50035)</p>
      </list>
      <p name="name">MGW_A</p>
    </managedObject>
    <managedObject class="ATM" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454/ATM-1" id="192614000003145148">
      <p name="lastSuccessfulUploadTimeStamp">21/07/15 01:32:40</p>
    </managedObject>
    <managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-0" id="192614000003415034">
      <p name="prSectionSdhExchangeTerminalIndex">1</p>
      <p name="protectionSwitchingMode">REV</p>
      <p name="protocolVariant">MSP</p>
      <p name="switchingDirection">WO</p>
      <p name="waitToRestoreTime">300</p>
      <p name="woSectionSdhExchangeTerminalIndex">0</p>
    </managedObject>
    <managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-1" id="192614000003415035">
      <p name="prSectionSdhExchangeTerminalIndex">3</p>
      <p name="protectionSwitchingMode">REV</p>
      <p name="protocolVariant">MSP</p>
      <p name="switchingDirection">WO</p>
      <p name="waitToRestoreTime">300</p>
      <p name="woSectionSdhExchangeTerminalIndex">2</p>
    </managedObject>
</input>

结果是:

<?xml version="1.0" encoding="utf-8"?>
<output>
   <managedObject class="MGW" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454"
                  id="192614000001726941">
      <list name="mgwOptions">
         <p>M3UA Interface (No 50035)</p>
      </list>
      <p name="name">MGW_A</p>
      <managedObject class="ATM" version="U5.0EP2" distName="PLMN-PLMN/MGW-219454/ATM-1"
                     id="192614000003145148">
         <p name="lastSuccessfulUploadTimeStamp">21/07/15 01:32:40</p>
         <managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-0"
                        id="192614000003415034">
            <p name="prSectionSdhExchangeTerminalIndex">1</p>
            <p name="protectionSwitchingMode">REV</p>
            <p name="protocolVariant">MSP</p>
            <p name="switchingDirection">WO</p>
            <p name="waitToRestoreTime">300</p>
            <p name="woSectionSdhExchangeTerminalIndex">0</p>
         </managedObject>
         <managedObject class="IFPG" version="A10TOP" distName="PLMN-PLMN/MGW-219454/ATM-1/IFPG-1"
                        id="192614000003415035">
            <p name="prSectionSdhExchangeTerminalIndex">3</p>
            <p name="protectionSwitchingMode">REV</p>
            <p name="protocolVariant">MSP</p>
            <p name="switchingDirection">WO</p>
            <p name="waitToRestoreTime">300</p>
            <p name="woSectionSdhExchangeTerminalIndex">2</p>
         </managedObject>
      </managedObject>
   </managedObject>
</output>