как получить некоторые документы из одного XML - PullRequest
1 голос
/ 23 января 2012

Я хотел бы получить отдельные документы из моего xml на нескольких уровнях.

Мой xml-файл:

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <line id="0">
        <Info><![CDATA[Header]]></Info>
        <documentNUM><![CDATA[DOC1]]></documentNUM>
        <Code><![CDATA[AS22]]></Code>
    </line>
    <line id="1">
        <Info><![CDATA[Line]]></Info>
        <Position><![CDATA[1]]></Position>
        <Number><![CDATA[7361]]></Number>
    </line>
    <line id="2">
        <Info><![CDATA[Line]]></Info>
        <Position><![CDATA[2]]></Position>
        <Number><![CDATA[7362]]></Number>
    </line>     
    <line id="3">
        <Info><![CDATA[Header]]></Info>
        <documentNUM><![CDATA[DOC2]]></documentNUM>
        <Code><![CDATA[AS22]]></Code>
    </line>
    <line id="4">
        <Info><![CDATA[Line]]></Info>
        <Position><![CDATA[1]]></Position>
        <Number><![CDATA[3623]]></Number>
    </line> 
    <line id="5">
        <Info><![CDATA[Header]]></Info>
        <documentNUM><![CDATA[DOC1]]></documentNUM>
        <Code><![CDATA[AS22]]></Code>
    </line>
    <line id="6">
        <Info><![CDATA[Line]]></Info>
        <Position><![CDATA[1]]></Position>
        <Number><![CDATA[3623]]></Number>
    </line> 
</document>

Из этого xml я должен получить два документа, для него я использую ключевую функцию:

<xsl:key name="kNext" match="line[starts-with(Info,'H')]" use="concat(starts-with(Info,'H'), '+', documentNUM)"/>

И для обоих документов 3 и1 строка.

Необходимый результат:

<result>
    <Group>
        <Message>
            <document>
                <documentNUM>DOC1</documentNUM> 
                <Lines>
                    <Line>
                        <LineNumber>1</LineNumber>
                        <Number>7361</Number>
                        <Code>AS22</Code>
                    </Line>
                    <Line>
                        <LineNumber>2</LineNumber>
                        <Number>7362</Number>
                        <Code>AS22</Code>
                    </Line>
                    <Line>
                        <LineNumber>3</LineNumber>
                        <Number>3623</Number>
                        <Code>AS22</Code>
                    </Line>
                </Lines>
            </document>
        </Message>
    </Group>
    <Group>
        <Message>
            <document>
                <documentNUM>DOC2</documentNUM>
            </document> 
                    <Line>
                        <LineNumber>1</LineNumber>
                        <Number>3623</Number>
                        <Code>AS22</Code>
                    </Line>
                </Lines>
        </Message>
    </Group>
</result>

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

PS Пожалуйста, исправьте мой вопрос, если это необходимо.

Ответы [ 2 ]

2 голосов
/ 24 января 2012

Вот полное решение XSLT 1.0 :

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

 <xsl:key name="kFollowing" match="line[not(documentNUM)]"
  use="generate-id(preceding-sibling::line
                               [documentNUM]
                                          [1]
                  )"/>

 <xsl:key name="kLineByDocNum" match="line"
  use="documentNUM"/>

 <xsl:template match=
  "line
     [documentNUM
    and
      generate-id()
     =
      generate-id(key('kLineByDocNum', documentNUM)[1])
     ]">
   <Group>
    <Message>
      <document>
        <documentNUM>
          <xsl:value-of select="documentNUM"/>
        </documentNUM>
        <Lines>
          <xsl:apply-templates mode="inGroup" select=
          "key('kLineByDocNum', documentNUM)"/>
        </Lines>
      </document>
    </Message>
   </Group>
 </xsl:template>

 <xsl:template match="line" mode="inGroup">
  <xsl:apply-templates mode="inGroup2"
  select="key('kFollowing', generate-id())">
  <xsl:with-param name="pCode" select="Code"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="line" mode="inGroup2">
  <xsl:param name="pCode"/>

  <xsl:variable name="vcurDocNum" select=
  "preceding-sibling::line
            [documentNUM][1]
                  /documentNUM
  "/>
  <xsl:variable name="vPos" select=
  "count(preceding-sibling::line
                [not(documentNUM)]
                  [preceding-sibling::line
                     [documentNUM][1]
                         /documentNUM
                  =
                   $vcurDocNum
                  ]
        ) +1"/>
  <Line>
    <LineNumber><xsl:value-of select="$vPos"/></LineNumber>
    <xsl:copy-of select="Number"/>
    <Code><xsl:value-of select="$pCode"/></Code>
  </Line>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

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

<document>
    <line id="0">
        <Info>Header</Info>
        <documentNUM>DOC1</documentNUM>
        <Code>AS22</Code>
    </line>
    <line id="1">
        <Info>Line</Info>
        <Position>1</Position>
        <Number>7361</Number>
    </line>
    <line id="2">
        <Info>Line</Info>
        <Position>2</Position>
        <Number>7362</Number>
    </line>
    <line id="3">
        <Info>Header</Info>
        <documentNUM>DOC2</documentNUM>
        <Code>AS22</Code>
    </line>
    <line id="4">
        <Info>Line</Info>
        <Position>1</Position>
        <Number>3623</Number>
    </line>
    <line id="5">
        <Info>Header</Info>
        <documentNUM>DOC1</documentNUM>
        <Code>AS22</Code>
    </line>
    <line id="6">
        <Info>Line</Info>
        <Position>1</Position>
        <Number>3623</Number>
    </line>
</document>

желаемый, правильный результат получается :

<Group>
   <Message>
      <document>
         <documentNUM>DOC1</documentNUM>
         <Lines>
            <Line>
               <LineNumber>1</LineNumber>
               <Number>7361</Number>
               <Code>AS22</Code>
            </Line>
            <Line>
               <LineNumber>2</LineNumber>
               <Number>7362</Number>
               <Code>AS22</Code>
            </Line>
            <Line>
               <LineNumber>3</LineNumber>
               <Number>3623</Number>
               <Code>AS22</Code>
            </Line>
         </Lines>
      </document>
   </Message>
</Group>
<Group>
   <Message>
      <document>
         <documentNUM>DOC2</documentNUM>
         <Lines>
            <Line>
               <LineNumber>1</LineNumber>
               <Number>3623</Number>
               <Code>AS22</Code>
            </Line>
         </Lines>
      </document>
   </Message>
</Group>
0 голосов
/ 23 января 2012

Это похоже на проблему группировки. Если у вас есть XSLT 2.0, используйте for-each-group / group-starting-with. Тогда вам не нужен ключ:

<result>
  <xsl:for-each-group select="line"
       group-starting-with="line[starts-with(Info,'H')]">
    <Group>
      <Message>
        <document>
          <documentNUM>
            <xsl:value-of select="current-grouping-key()/documentNUM" />
          </documentNUM>
        </document>
        <xsl:apply-templates select="current-group()
                          [not(starts-with(Info, 'H'))]" />

и т.д.

Если вы хотите больше подробностей, дайте мне знать.

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