【问题标题】:copy a complete XML tree except for some branches based on a criteria复制一个完整的 XML 树,除了一些基于条件的分支
【发布时间】:2015-11-16 08:51:36
【问题描述】:

我有一个可能包含零件本身的零件列表。实际上是物料清单 (BOM)。一些部件具有将它们标识为“备件”的元素。在将我的转换为另一个 XML 文件时,我只对包含“备件”的节点(和祖先)感兴趣,换句话说,<Spare_part_indicator> 但也维护该特定节点中的所有兄弟姐妹。 这是我作为 XML 的示例 BOM:

    <Level levelNo="1">
        <Component_number>HEKT109476R4</Component_number>
        <Object_description>KEY INTERLOCK</Object_description>
        <Level levelNo="2">
            <Component_number>HENS434350</Component_number>
            <Object_description>LOCK BARREL (PLACEHOLDER)</Object_description>
        </Level>
        <Level levelNo="2">
            <Component_number>HEKT460536P3</Component_number>
            <Object_description>SWITCH_SEC:_PSEN ME1S/1AR_2O/2S</Object_description>
            <Spare_part_indicator>2</Spare_part_indicator>
            <Sort_String>S420</Sort_String>
            <QR_code>HEKT460536P3.png</QR_code>
        </Level>
        <Level levelNo="2">
            <Component_number>HEKT460751R2</Component_number>
            <Object_description>SHEET METAL</Object_description>
            <Level levelNo="3">
                <Component_number>HEKT323873P1</Component_number>
                <Object_description>C-PAN</Object_description>
            </Level>
            <Level levelNo="3">
                <Component_number>HEKT453450P5</Component_number>
                <Object_description>HIGH VOLTAGE CAPACITOR 5NF/30KV 10%</Object_description>
                <Spare_part_indicator>3</Spare_part_indicator>
                <QR_code>HEKT453450P5.png</QR_code>
            </Level>
        </Level>
    </Level>
    <Level levelNo="1">
        <Component_number>HEKT109444R3</Component_number>
        <Object_description>FILTER NETWORK 500KW</Object_description>
        <Level levelNo="2">
            <Component_number>HEKT457790P1</Component_number>
            <Object_description>BRACKET</Object_description>
        </Level>
        <Level levelNo="2">
            <Component_number>HEKT323840P1</Component_number>
            <Object_description>COIL</Object_description>
            <Spare_part_indicator>3</Spare_part_indicator>
            <Sort_String>L401</Sort_String>
            <QR_code>HEKT323840P1.png</QR_code>
        </Level>
    </Level>

现在我想将上面的列表转换成一个新的 XML 树,它只包含元素为 &lt;Spare_part_indicator&gt; 的节点,但保持层次结构,包括祖先。我遇到了以下 XSL 样式表,经过一些修改,它完全符合我的要求。但不幸的是,它只留下了元素 &lt;Spare_part_indicator&gt; 并删除了所有其他元素,例如 Component_numberetc。

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

 <xsl:param name="subSelectionXPath"
  select="//Spare_part_indicator"
  />

 <xsl:template match="*">
  <xsl:choose>
   <xsl:when test=
   "descendant::node()
        [count(.|$subSelectionXPath)
        =
         count($subSelectionXPath)
        ]
   ">
   <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="*"/>
   </xsl:copy>
  </xsl:when>

   <xsl:when test=
   "count(.|$subSelectionXPath)
   =
    count($subSelectionXPath)
   ">
   <xsl:copy-of select="."/>

   </xsl:when>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

上述 BOM 的预期结果应如下所示:

<Level levelNo="1">
    <Component_number>HEKT109476R4</Component_number>
    <Object_description>KEY INTERLOCK</Object_description>
    <Level levelNo="2">
        <Component_number>HEKT460536P3</Component_number>
        <Object_description>SWITCH_SEC:_PSEN ME1S/1AR_2O/2S</Object_description>
        <Spare_part_indicator>2</Spare_part_indicator>
        <Sort_String>S420</Sort_String>
        <QR_code>HEKT460536P3.png</QR_code>
    </Level>
    <Level levelNo="2">
        <Component_number>HEKT460751R2</Component_number>
        <Object_description>SHEET METAL</Object_description>
        <Level levelNo="3">
            <Component_number>HEKT453450P5</Component_number>
            <Object_description>HIGH VOLTAGE CAPACITOR 5NF/30KV 10%</Object_description>
            <Spare_part_indicator>3</Spare_part_indicator>
            <QR_code>HEKT453450P5.png</QR_code>
        </Level>
    </Level>
</Level>
<Level levelNo="1">
    <Component_number>HEKT109444R3</Component_number>
    <Object_description>FILTER NETWORK 500KW</Object_description>
    <Level levelNo="2">
        <Component_number>HEKT323840P1</Component_number>
        <Object_description>COIL</Object_description>
        <Spare_part_indicator>3</Spare_part_indicator>
        <Sort_String>L401</Sort_String>
        <QR_code>HEKT323840P1.png</QR_code>
    </Level>
</Level>

到目前为止,我还想不通,我怎样才能保留同级元素,以及父节点中的元素以及这里和那里的提示,将不胜感激。 我希望我能正确描述问题,请耐心等待,因为我才刚刚开始发现 XSL 样式表的强大功能。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    嗯……

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes"/>
    
      <!-- copy everything -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <!-- except levels without Spare_part_indicator anywhere inside -->
      <xsl:template match="Level[not(.//Spare_part_indicator)]"/>
    
    </xsl:stylesheet>
    

    【讨论】:

    • 反应真快!正是我想要实现的目标
    • XSLT 是声明性的,重要的是彻底了解您想要实现的目标,而不是开始考虑如何实现它。如您所见,解决方案非常简单且非常“声明性”。
    • 确实,解决方案很简单,正如您所说的“声明式”。我还想问一个问题。生成的 xml 文档包含忽略节点的空格(换行符)。只是好奇如何在同一个样式表中避免这种情况?这并不是一个问题,因为下面的 XSL-FO 转换并不关心它。我只是好奇。谢谢
    • 在 xsl:output 下添加
    • 非常感谢。实际上这是我在问之前所做的,但我猜我做错了什么,Xalan 中止了翻译。现在它工作正常。非常感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多