Как создать XML из других метаданных XML? - PullRequest
1 голос
/ 06 апреля 2009

Я не уверен, что название ясно объясняет мою проблему, постараюсь включить как можно больше подробностей.

Мне нужно преобразовать ниже xml в правильно отформатированный файл, используя Xslt 1, чтобы я мог десериализовать его в тип .net.

Исходный XML

            <ax21:result type="test.ws.Result">
                <ax21:columnNames>fileName</ax21:columnNames>
                <ax21:columnNames>lockedState</ax21:columnNames>
                <ax21:columnNames>currentLockOwner</ax21:columnNames>
                <ax21:columnNames>UUID</ax21:columnNames>
                <ax21:resultData>Test1.doc</ax21:resultData>
                <ax21:resultData>true</ax21:resultData>
                <ax21:resultData>analyst</ax21:resultData>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
                <ax21:resultData>Test2.doc</ax21:resultData>
                <ax21:resultData>false</ax21:resultData>
                <ax21:resultData/>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
                <ax21:resultData>Test3.doc</ax21:resultData>
                <ax21:resultData>true</ax21:resultData>
                <ax21:resultData>analyst</ax21:resultData>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
                <ax21:resultData>Test4.doc</ax21:resultData>
                <ax21:resultData>false</ax21:resultData>
                <ax21:resultData/>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
            </ax21:result>

Целевой XML

<result>
    <item>
        <fileName>Test1.doc</fileName>
        <lockedState>true</lockedState>
        <currentLockOwner>analyst</currentLockOwner>
        <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
    </item>
    <item>
        <fileName>Test2.doc</fileName>
        <lockedState>true</lockedState>
        <currentLockOwner>analyst</currentLockOwner>
        <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
    </item>
    <item>
        <fileName>Test2.doc</fileName>
        <lockedState>true</lockedState>
        <currentLockOwner>analyst</currentLockOwner>
        <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
    </item>
</result>

Можно ли это сделать с помощью xslt? Если да, пожалуйста, опубликуйте ссылку или образец xslt, чтобы я попробовал.

Я использую .net 2.0, c #, XSLT 1.0

Ответы [ 2 ]

3 голосов
/ 06 апреля 2009

Это одно довольно короткое и простое решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ax21="my:ax21" exclude-result-prefixes="ax21"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vCols" select="/*/ax21:columnNames"/>
  <xsl:variable name="vNumCols" select="count($vCols)"/>

    <xsl:template match="ax21:result">
        <result>
          <xsl:apply-templates select=
           "ax21:resultData[position() mod $vNumCols = 1]"
           />
        </result>
    </xsl:template>

    <xsl:template match="ax21:resultData">
      <item>
        <xsl:apply-templates mode="create" select=
         "(.|following-sibling::ax21:resultData)
                               [not(position() > $vNumCols) ]
         "/>
      </item>
    </xsl:template>

    <xsl:template match="ax21:resultData" mode="create">
      <xsl:variable name="vPos" select="position()"/>
    <xsl:element name="{$vCols[$vPos]}">
          <xsl:value-of select="."/>
          <xsl:if test="not(text())">
            <xsl:value-of select=
             "(.| preceding-sibling::ax21:resultData)
                         [position() mod $vNumCols = $vPos]
                            [text()]
                                  [last()]
             "/>
          </xsl:if>
    </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к следующему документу XML :

<ax21:result type="test.ws.Result"
 xmlns:ax21="my:ax21"
>
    <ax21:columnNames>fileName</ax21:columnNames>
    <ax21:columnNames>lockedState</ax21:columnNames>
    <ax21:columnNames>currentLockOwner</ax21:columnNames>
    <ax21:columnNames>UUID</ax21:columnNames>
    <ax21:resultData>Test1.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test2.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test3.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test4.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
</ax21:result>

желаемый результат получен :

<result>
   <item>
      <fileName>Test1.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test2.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test3.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test4.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
</result>

Объяснение

  1. Для удобства имена столбцов и их номера собраны в глобальные переменные $vCols и $vNumCols.

  2. Мы применяем шаблоны к каждому N-му ax21:resultData элементу, где N mod $vNumCols = 1. Каждый такой элемент начинает новый item.

  3. Каждый элемент ax21:resultData, который будет первым в item, сопоставляется с шаблоном в режиме "без режима". Это просто создает элемент обтекания item и применяет ко всем текущим элементам $ vNumCols ax21:resultData другой шаблон - в режиме "create".

  4. Шаблон в режиме "create" просто создает элемент, имя которого является значением n-го элемента в $vCols, где n - это position() узла current () для который шаблон применяется.

  5. Наконец, если получится, что значение не было предоставлено, мы получим (в обратном порядке) последнее непустое значение для элемента того же типа.

0 голосов
/ 06 апреля 2009

Будет очень трудно, если не невозможно, сделать это правильно и надежно.

Проблема в том, что на множестве и узлах нет указателей на индекс или тип относительно их типа / позиции - вам нужно более или менее угадать ...

Это была бы другая история, если бы, по крайней мере, у нее был дополнительный атрибут, что-то вроде и так далее, - таким образом можно было бы каким-то образом связать их вместе.

Есть ли хоть какой-нибудь шанс, что вы могли бы немного "массировать" исходные данные ?? В противном случае, я бы сказал, что вам придется загрузить его в C #, проанализировать его и выполнить много ручной обработки, чтобы получить то, что вы хотите.

Марк

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