Проверьте значение в строке XML с помощью xsl - PullRequest
0 голосов
/ 21 февраля 2019

Я новичок в форуме и даже (немного) новичок в xsl;Мне нужна помощь, чтобы решить небольшую проблему с XML-кодом: пожалуйста, посмотрите на структуру ниже.

*********************************
<ProductRevision id="id45" **************>
  <ApplicationRef **************/>
  <UserData *********>
  <UserValue title="title1" value="11111 000 000"/>
  <UserValue title="object_name" value="test name1"/>
  </UserData>
  </ProductRevision>
<ProductRevision id="id50" ***********>
  <ApplicationRef **************/>
  <UserData id="id46">
  <UserValue title="title1" value="22222 000 000"/>
  <UserValue title="object_name" value="test name2"/>
  </UserData>
  </ProductRevision>
*******************************************
<GeneralRelation id="id49" subType="TestType" relatedRefs="#id2 #id45">
  <ApplicationRef **************/>
  <UserData ********>
  <UserValue title="ds5_amont" type="int" value="3"/>
  <UserValue title="ds5_cavities" type="int" value="2"/>
  </UserData>
  </GeneralRelation>
<GeneralRelation id="id49" subType="TestType" relatedRefs="#id2 #id50">
  <ApplicationRef ***********/>
  <UserData **********>
  <UserValue title="ds5_amont" type="int" value="2"/>
  <UserValue title="ds5_cavities" type="int" value="3"/>
  </UserData>
  </GeneralRelation>

Как видите, узлы ProductRevision содержат значение id;это значение определяет два соответствующих узла GeneralRelation, которые содержат значения UserValues ​​ ds5_amont и ds5_cavities .Я использую следующий фрагмент кода .xsl для отображения значений title1 и object_name всех узлов ProductRevision:

<xsl:for-each select="//plm:ProductRevision[@subType = 'XXXXX']">
  <xsl:variable name="part" select="./plm:UserData/plm:UserValue[@title='object_name']/@value" />
  <xsl:variable name="identnr" select="./plm:UserData/plm:UserValue[@title='title1']/@value" />
<Row>
  <Cell ss:StyleID="s73">
  <Data ss:Type="String">
  <xsl:value-of select="$part"/>
  </Data>
  </Cell>
  <Cell ss:StyleID="s73">
  <Data ss:Type="String">
  <xsl:value-of select="$identnr"/>
  </Data> 
  </Cell> 
</Row> 

Теперь для каждого ProductRevision мне нужно отобразить соответствующий ds5_amont и ds5_cavities значения, содержащиеся в соответствующих узлах, идентифицированных значениями id45 и id50 .Эти свойства должны быть напечатаны рядом с ячейками, в которых отображаются переменные $ part и $ identnr.До сих пор я не смог найти решение, любая помощь будет высоко оценена!Спасибо!

РЕДАКТИРОВАТЬ

Извините, ребята, я не могу за 2 секунды узнать, как воспроизвести таблицу Excel на вашем форуме.Результат должен быть просто таким: для каждой редакции Продукта должна быть одна строка, показывающая имя_объекта **** title1 **** ds5_amont **** ds5_cavities Извините еще раз, надеюсь, это достаточно ясно;-)

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

Вы хотите обработать те элементы GeneralRelation, которые имеют значение @id текущего элемента ProductRevision в списке их атрибута @relatedRefs.В XSLT 1.0 вы используете contains и current такие функции:

/root
  /GeneralRelation
    [contains
       (concat(@relatedRefs,' '),
        concat('#',current()/@id,' ')
       )
    ]

Этот вход:

<root>
    <ProductRevision id="id45">
        <ApplicationRef />
        <UserData>
            <UserValue title="title1" value="11111 000 000" />
            <UserValue title="object_name" value="test name1" />
        </UserData>
    </ProductRevision>
    <ProductRevision id="id50">
        <ApplicationRef />
        <UserData id="id46">
            <UserValue title="title1" value="22222 000 000" />
            <UserValue title="object_name" value="test name2" />
        </UserData>
    </ProductRevision>
    <GeneralRelation id="id49" subType="TestType"
        relatedRefs="#id2 #id45">
        <ApplicationRef />
        <UserData>
            <UserValue title="ds5_amont" type="int" value="453" />
            <UserValue title="ds5_cavities" type="int" value="452" />
        </UserData>
    </GeneralRelation>
    <GeneralRelation id="id49" subType="TestType"
        relatedRefs="#id2 #id50">
        <ApplicationRef />
        <UserData>
            <UserValue title="ds5_amont" type="int" value="502" />
            <UserValue title="ds5_cavities" type="int" value="503" />
        </UserData>
    </GeneralRelation>
</root>

Иэто преобразование

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" />

    <xsl:variable name="vGeneralRelation" 
        select="/root/GeneralRelation" />

    <xsl:template match="text()|GeneralRelation" />
    <xsl:template match="root">
        <table>
            <xsl:apply-templates />
        </table>
    </xsl:template>

    <xsl:template match="ProductRevision">
        <Row>
            <xsl:apply-templates
                select="*|$vGeneralRelation[
                    contains(concat(@relatedRefs,' '),
                        concat('#',current()/@id,' '))]/*" />
        </Row>
    </xsl:template>

    <xsl:template
        match="UserValue[@title[.='object_name' or .='title1' or .='ds5_cavities' or .='ds5_amont']]">
        <Cell>
            <xsl:value-of select="@value" />
        </Cell>
    </xsl:template>
</xsl:stylesheet>

Произведите этот вывод

<?xml version="1.0" encoding="utf-8"?>
<table>
   <Row>
      <Cell>11111 000 000</Cell>
      <Cell>test name1</Cell>
      <Cell>453</Cell>
      <Cell>452</Cell>
   </Row>
   <Row>
      <Cell>22222 000 000</Cell>
      <Cell>test name2</Cell>
      <Cell>502</Cell>
      <Cell>503</Cell>
   </Row>
</table>

Проверьте рабочий пример на http://xsltransform.net/6qaFCEU

0 голосов
/ 26 февраля 2019

Спасибо всем за ваш вклад.Наконец, это решение, которое я использовал.Полагаю, у вас были очень сложные и профессиональные решения, но для такого начинающего, как я, необходимо упростить код таким образом, чтобы даже ошибки можно было легко идентифицировать.Но я могу сказать вам, что я буду много изучать эти решения!Прежде всего, определите правильные ProductRevision узлы по атрибуту subType ;затем отобразите две переменные в контексте узлов ProductRevision и сохраните идентификатор в переменной pid :

    <xsl:template match="//plm:ProductRevision[@subType='DS5_PartRevision']">

    <xsl:variable name="part" select="./plm:UserData/plm:UserValue[@title='object_name']/@value" />
    <xsl:variable name="identnr" select="./plm:UserData/plm:UserValue[@title='ds5_s_serien_identnr']/@value" />
    <xsl:variable name="pid" select="@id"/>

    <Row>

        <Cell ss:StyleID="s73">
            <Data ss:Type="String">
                <xsl:value-of select="$part"/>
            </Data>
        </Cell>
        <Cell ss:StyleID="s73">
            <Data ss:Type="String">
                <xsl:value-of select="$identnr"/>
            </Data>  
        </Cell> 

После обработки первого узла ProductRevision проверьте все GeneralRelation узлы;для каждого узла создайте переменную relref и сохраните часть значения атрибута relatedRefs .Будет сохранено только значение после "#" (пробел #):

<xsl:for-each select="/plm:PLMXML/plm:GeneralRelation">
            <xsl:variable name="relref" select="substring-after(@relatedRefs,' #')"/>

            <xsl:choose>
                <xsl:when test="$relref=$pid">
                    <Cell ss:StyleID="s73">
                        <Data ss:Type="String">
                            <xsl:value-of select="./plm:UserData/plm:UserValue[@title='ds5_amont']/@value"/>
                        </Data>  
                    </Cell>
                    <Cell ss:StyleID="s73">
                        <Data ss:Type="String">
                            <xsl:value-of select="./plm:UserData/plm:UserValue[@title='ds5_cavities']/@value"/>
                        </Data>  
                    </Cell>
                </xsl:when>
            </xsl:choose>
        </xsl:for-each>

    </Row>

Для каждого узла GeneralRelation сравните значения pid и relref :если они совпадают, получите значения двух свойств в контексте узла GeneralRelation (следовательно, обозначение ./plm/) и отобразите их в правильной строке (соответствующего ProductRevision).

0 голосов
/ 21 февраля 2019

Используя процессор libxslt, вы можете воспользоваться функцией расширения EXSLT str:tokenize().

Рассмотрим следующий упрощенный пример:

XML

<root>
  <ProductRevision id="id45">
    <ApplicationRef/>
    <UserData>
      <UserValue title="title1" value="11111 000 000"/>
      <UserValue title="object_name" value="test name1"/>
    </UserData>
  </ProductRevision>
  <ProductRevision id="id50">
    <ApplicationRef/>
    <UserData id="id46">
      <UserValue title="title1" value="22222 000 000"/>
      <UserValue title="object_name" value="test name2"/>
    </UserData>
  </ProductRevision>
  <GeneralRelation id="id49" subType="TestType" relatedRefs="#id2 #id45">
    <ApplicationRef/>
    <UserData>
      <UserValue title="ds5_amont" type="int" value="453"/>
      <UserValue title="ds5_cavities" type="int" value="452"/>
    </UserData>
  </GeneralRelation>
  <GeneralRelation id="id49" subType="TestType" relatedRefs="#id2 #id50">
    <ApplicationRef/>
    <UserData>
      <UserValue title="ds5_amont" type="int" value="502"/>
      <UserValue title="ds5_cavities" type="int" value="503"/>
    </UserData>
  </GeneralRelation>
</root>

XSLT 1.0 + EXSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="relation" match="GeneralRelation" use="str:tokenize(@relatedRefs, ' ')" />

<xsl:template match="/root">
    <table>
        <xsl:for-each select="ProductRevision">
            <Row>
                <!-- ProductRevision -->
                <Cell>
                    <xsl:value-of select="UserData/UserValue[@title='object_name']/@value"/>
                </Cell>
                <Cell>
                    <xsl:value-of select="UserData/UserValue[@title='title1']/@value"/>
                </Cell>
                <!-- GeneralRelation -->
                <xsl:variable name="relation" select="key('relation', concat('#', @id))" />
                <Cell>
                    <xsl:value-of select="$relation/UserData/UserValue[@title='ds5_amont']/@value"/>
                </Cell>
                <Cell>
                    <xsl:value-of select="$relation/UserData/UserValue[@title='ds5_cavities']/@value"/>
                </Cell>
            </Row> 
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>

Результат

<?xml version="1.0" encoding="UTF-8"?>
<table>
  <Row>
    <Cell>test name1</Cell>
    <Cell>11111 000 000</Cell>
    <Cell>453</Cell>
    <Cell>452</Cell>
  </Row>
  <Row>
    <Cell>test name2</Cell>
    <Cell>22222 000 000</Cell>
    <Cell>502</Cell>
    <Cell>503</Cell>
  </Row>
</table>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...