Как получить дочерние узлы, если дочерний узел имеет другой атрибут? - PullRequest
0 голосов
/ 03 июня 2019

В программном обеспечении 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. Проверьте, совпадает ли атрибут идентификатора singlepart с атрибутом basepart прокси-узла (singlepart является дочерним узлом прокси-узла).
  2. Получить ключевой атрибут узла покрытия (покрытие является дочерним узлом одной части)
  3. Проверьте, совпадает ли ключевой атрибут из # 2 со значением / modelExtract / header / project / UserProjAttr, в данном случае 'G', которое я назвал mainfinish переменная.
  4. Если № 3 - да, тогда весь основной узел можно игнорировать.
  5. Если № 3 - нет, то циклически проходить через каждый отдельный узел и проверять, совпадает ли ключевой атрибут со значением mainfinish .
  6. Если № 3 - да, скопируйте этот отдельный узел, в противном случае пропустите его.

Будучи относительно новичком в 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 Ответ

2 голосов
/ 03 июня 2019

Одна из проблем, с которой вы столкнулись, связана с этой строкой

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

Это шаблон, соответствующий mainpart, поэтому вышеприведенный оператор ищет другой mainpart, который является дочерним по отношению к текущему * 1006.* которого явно не существует

Вам действительно не нужно 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>

Делатьобратите внимание, что в XSLT 1.0 считается ошибкой использовать имена переменных в совпадениях с шаблонами, поэтому во втором показанном XSLT удалено namedfinish.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...