拆分XMLTYPE以根据条件创建两个XMLTYPES

时间:2014-09-05 16:45:48

标签: sql xml oracle plsql xmltype

我有一个Oracle表,其中包含存储在XMLTYPE中的多个XML文件。虽然我可以查询和更新XML类型,但我正在尝试编写一个过程,它将获取一个XML,并根据某些条件将两个新的XMLTYPES插入到同一个表中。

例如,如果以下内容存储在我的XMLTYPE中,我想创建两条消息,两条消息都包含所有标题信息,但其中一条包含消息行,其中排名/位置最多为5(将返回两行)和其他排名/位置大于5(将返回三行):

<DistrictMsg timestamp="2014-09-05T04:45:00">
  <Publication xmlns:ns1="http://www.mynamespace.co.uk">
    <TopicID>ENGLISH_DISTRICTS</TopicID>
  </Publication>
  <Message xmlns="http://www.mynamespace.co.uk">
    <ns1:MessageHeader xmlns:ns1="http://www.mynamespace.co.uk">
      <ns1:MessageType>
        <ns1:ID>EnglishDistricts2014</ns1:ID>
      </ns1:MessageType>
      <ns1:DocType>
        <ns1:InternalName>
          <ns1:ID>DistrictByPopulation</ns1:ID>
        </ns1:InternalName>
      </ns1:DocType>
    </ns1:MessageHeader>
    <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
      <ns1:District>
        <ns1:Name>Birmingham</ns1:Name>
      </ns1:District>
      <ns1:Population measure="1000">1074.3</ns1:Population>
      <DistRank>
        <PopulationRank>
            <Position>1</Position>
        </PopulationRank>
      </DistRank>
    </ns1:MessageLine>
    <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
      <ns1:District>
        <ns1:Name>Manchester</ns1:Name>
      </ns1:District>
      <ns1:Population measure="1000">502.9</ns1:Population>
      <DistRank>
        <PopulationRank>
            <Position>7</Position>
        </PopulationRank>
      </DistRank>
    </ns1:MessageLine>
    <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
      <ns1:District>
        <ns1:Name>Liverpool</ns1:Name>
      </ns1:District>
      <ns1:Population measure="1000">465.7</ns1:Population>
      <DistRank>
        <PopulationRank>
            <Position>9</Position>
        </PopulationRank>
      </DistRank>
    </ns1:MessageLine>
    <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
      <ns1:District>
        <ns1:Name>Doncaster</ns1:Name>
      </ns1:District>
      <ns1:Population measure="1000">302.5</ns1:Population>
      <DistRank>
        <PopulationRank>
            <Position>34</Position>
        </PopulationRank>
      </DistRank>
    </ns1:MessageLine>
    <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
      <ns1:District>
        <ns1:Name>Cornwall</ns1:Name>
      </ns1:District>
      <ns1:Population measure="1000">533.8</ns1:Population>
      <DistRank>
        <PopulationRank>
            <Position>4</Position>
        </PopulationRank>
      </DistRank>      
    </ns1:MessageLine>
  </Message>
</DistrictMsg>

1 个答案:

答案 0 :(得分:0)

您可以通过使用deletexml删除不需要的条目来执行此操作。要将这些条目最多返回5,我删除了所有大于5的条目。同样,为了返回大于5的条目,我删除了小于或等于5的条目。 这是我的解决方案,希望有所帮助:

            with xml_data as(
            select xmltype('
            <DistrictMsg timestamp="2014-09-05T04:45:00">
              <Publication xmlns:ns1="http://www.mynamespace.co.uk">
                <TopicID>ENGLISH_DISTRICTS</TopicID>
              </Publication>
              <Message xmlns="http://www.mynamespace.co.uk">
                <ns1:MessageHeader xmlns:ns1="http://www.mynamespace.co.uk">
                  <ns1:MessageType>
                    <ns1:ID>EnglishDistricts2014</ns1:ID>
                  </ns1:MessageType>
                  <ns1:DocType>
                    <ns1:InternalName>
                      <ns1:ID>DistrictByPopulation</ns1:ID>
                    </ns1:InternalName>
                  </ns1:DocType>
                </ns1:MessageHeader>
                <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
                  <ns1:District>
                    <ns1:Name>Birmingham</ns1:Name>
                  </ns1:District>
                  <ns1:Population measure="1000">1074.3</ns1:Population>
                  <DistRank>
                    <PopulationRank>
                        <Position>1</Position>
                    </PopulationRank>
                  </DistRank>
                </ns1:MessageLine>
                <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
                  <ns1:District>
                    <ns1:Name>Manchester</ns1:Name>
                  </ns1:District>
                  <ns1:Population measure="1000">502.9</ns1:Population>
                  <DistRank>
                    <PopulationRank>
                        <Position>7</Position>
                    </PopulationRank>
                  </DistRank>
                </ns1:MessageLine>
                <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
                  <ns1:District>
                    <ns1:Name>Liverpool</ns1:Name>
                  </ns1:District>
                  <ns1:Population measure="1000">465.7</ns1:Population>
                  <DistRank>
                    <PopulationRank>
                        <Position>9</Position>
                    </PopulationRank>
                  </DistRank>
                </ns1:MessageLine>
                <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
                  <ns1:District>
                    <ns1:Name>Doncaster</ns1:Name>
                  </ns1:District>
                  <ns1:Population measure="1000">302.5</ns1:Population>
                  <DistRank>
                    <PopulationRank>
                        <Position>34</Position>
                    </PopulationRank>
                  </DistRank>
                </ns1:MessageLine>
                <ns1:MessageLine xmlns:ns1="http://www.mynamespace.co.uk">
                  <ns1:District>
                    <ns1:Name>Cornwall</ns1:Name>
                  </ns1:District>
                  <ns1:Population measure="1000">533.8</ns1:Population>
                  <DistRank>
                    <PopulationRank>
                        <Position>4</Position>
                    </PopulationRank>
                  </DistRank>      
                </ns1:MessageLine>
              </Message>
            </DistrictMsg>') xtype
            from dual)
            select 
            xmlserialize(document 
            deletexml(xtype, '//ns1:MessageLine[ns1:DistRank/ns1:PopulationRank/ns1:Position[text()>5]]', 'xmlns:ns1="http://www.mynamespace.co.uk"')  
            as clob indent size = 2) up_to_five,
            xmlserialize(document 
            deletexml(xtype, '//ns1:MessageLine[ns1:DistRank/ns1:PopulationRank/ns1:Position[text()<=5]]', 'xmlns:ns1="http://www.mynamespace.co.uk"')  
            as clob indent size = 2) greater_than_five
            from xml_data;