如果子节点具有不同的属性,如何获得子兄弟节点?

时间:2019-06-03 06:53:22

标签: xslt

在软件Advance Steel中,可以结合使用xslt文件和报告模板来进一步过滤出报告。 xslt文件读取最初创建的xml文件。下面是示例xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<modelExtract xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <header>
        <project>
            <name>D' Project</name>
            <number>2019</number>
            <client>ABC Builder</client>
            <buildingLocation>NewMla</buildingLocation>
            <UserProjAttr>G</UserProjAttr>
        </project>
    </header>
    <parts>
        <assembly name="1">
            <mainpart id="2455EC" num="1-MS19" quantity="1">
                <proxy id="24208E" ACADID="24208F" basepart="1D25B1">
                    <singlepart id="245580" num="1-m35" quantity="1">
                        <part id="1D25B1" name="C4X6.25" class="Beam" ACADID="1D2007" dstvName="C4X6.25">
                            <coating key="SP" name="SP"/>
                        </part>
                    </singlepart>
                    <singlepart id="2455B6" num="1-p7" quantity="1">
                        <explicitQuantity>1</explicitQuantity>
                        <part id="23C645" name="PL 3/8&quot;x6 1/2&quot;" class="Plate" ACADID="23C646" dstvName="PL 3/8&quot;">
                            <coating key="G" name="G"/>
                        </part>
                    </singlepart>
                    <singlepart id="242AE8" num="1-p8" quantity="1">
                        <explicitQuantity>1</explicitQuantity>
                        <part id="23C033" name="PL 3/8&quot;x7&quot;" class="Plate" ACADID="23C034" dstvName="PL 3/8&quot;">
                            <coating key="G" name="G"/>
                        </part>
                    </singlepart>
                </proxy>
            </mainpart>         
        </assembly>     
    </parts>
</modelExtract>

在xml文件中,这是获取输出所需的步骤。

  
      
  1. 检查单部分id属性是否与代理节点的basepart属性值相同(单部分是代理节点的子节点)。
  2.   
  3. 获取涂层节点的关键属性(涂层是单部分的子节点)
  4.   
  5. 检查#2中的key属性是否与/ modelExtract / header / project / UserProjAttr值相同,在本例中为'G',我将其命名为 mainfinish 变量。
  6.   
  7. 如果#3为是,则可以忽略整个mainpart节点。
  8.   
  9. 如果#3为否,则遍历每个单部分节点并检查key属性是否与 mainfinish 值相同。
  10.   
  11. 如果#3是,请复制该单部分节点,否则跳过它。
  12.   

作为xslt的新手,我无法获得想要的输出,而是所有单部分都已输出。这是我的xslt文件。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>  
  <xsl:variable name="namedfinish" select="/modelExtract/header/project/UserProjAttr5"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="mainpart" >
    <xsl:copy>
      <xsl:for-each select="mainpart/proxy" >
        <xsl:variable name="BaseId" select="mainpart/proxy/@basepart" />
        <xsl:variable name="mainfinish" select="singlepart/part[@id = $BaseId]/@key" />
        <xsl:template match="(singlepart/part/coating/@key != $mainfinish) "><!--error in this line-->
          <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
          </xsl:copy>
        </xsl:template>
      </xsl:for-each>       
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

我知道我的xslt文件有问题,但是由于是该领域的新手,所以我无法指出要使用的正确语法。 任何帮助将不胜感激。

这是我的xslt文件的另一个版本,现在它不会输出任何内容。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

  <xsl:variable name="namedfinish" select="/modelExtract/header/project/UserProjAttr5"/>

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

  <xsl:template match="mainpart" >
    <xsl:copy>
      <xsl:for-each select="mainpart/proxy" >
        <xsl:variable name="BaseId" select="mainpart/proxy/@basepart" />
        <xsl:variable name="mainfinish" select="singlepart/part[@id = $BaseId]/@key" />
        <xsl:for-each select="singlepart" >
          <xsl:choose>
            <xsl:when test="singlepart[not(contains((part/coating/@key), $mainfinish))] and singlepart[contains((part/coating/@key), $namedfinish)]" >
              <xsl:apply-templates select="@*|node()" />
            </xsl:when>
          </xsl:choose>
        </xsl:for-each>
      </xsl:for-each>       
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:2)

您遇到的问题是此行

<xsl:for-each select="mainpart/proxy" >

这是在与mainpart匹配的模板中,因此上面的语句正在寻找另一个mainpart的子元素,而该mainpart是当前xsl:for-each的子元素,显然不存在。

如果只会有一个proxy,那么您实际上并不需要xsl:copy

您还应该将xsl:if包裹在<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <xsl:output method="xml" encoding="UTF-8" indent="yes"/> <xsl:variable name="namedfinish" select="/modelExtract/header/project/UserProjAttr"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="mainpart" > <xsl:variable name="BaseId" select="proxy/@basepart" /> <xsl:variable name="mainfinish" select="proxy/singlepart/part[@id = $BaseId]/coating/@key" /> <xsl:if test="$mainfinish != $namedfinish"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:if> </xsl:template> <xsl:template match="proxy"> <xsl:copy> <xsl:apply-templates select="@*|singlepart[part/coating/@key = $namedfinish]" /> </xsl:copy> </xsl:template> </xsl:stylesheet> 中,以测试是否需要主体。

以这种方式尝试...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

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

  <xsl:template match="mainpart[proxy/singlepart/part[@id = ../../@basepart]/coating/@key = /modelExtract/header/project/UserProjAttr]" />

  <xsl:template match="singlepart[part/coating/@key != /modelExtract/header/project/UserProjAttr]" />
</xsl:stylesheet>

或者,由于拥有身份模板,该身份模板负责不变地复制所有节点,因此您可以重新编写它以拥有其他模板,这些模板与您不想复制的对象匹配。

namedfinish

请注意,在XSLT 1.0中在模板匹配中使用变量名称被认为是错误的,这就是为什么显示的第二个XSLT删除了select decode(lv,0,0,tot-prog) somma ,decode(lv,0,0,cnt-myrow) count from( select * from ( select pan,dt,flag,am, last_value(flag) over() lv, row_number() OVER (order by dt) AS myrow, count(*) over() cnt, case when lead(flag) OVER (ORDER BY dt) != flag then rownum end AS change, sum(am) over() tot, sum(am) over(order by dt) prog from test where pan=:pan and dt > :dt and flag is not null order by dt ) t where change is not null order by change desc ) where rownum =1 的原因。