Search code examples
xmlnamespacesmarklogicxsi

MarkLogic TDE on XML documents with XSD and XSI


Hello i am using MarkLogic 9.0 and have a beginner level of experience with ML and XML. I have followed the MarkLogic SQL Guide successfully and want to use it in the real world and extract from transactional xml files the the type element. But in the view which i created returns an empty result. I think it has something to do with the xsd and the xsi. But as I mentioned earlier I am at a beginner level and I don't know how to fix this.

The following text describe the scenario to reproduce the problem.

I load 3500 xml documents to the SQLData(with triple store index) I also created a SQLSchema database which is related tot the SQLData database as described in the Guide. All XML documents has a similar structure like the example below:

<?xml  version="1.0" encoding="UTF-8"?>
<scope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <item>
    <transaction>
      <type>CI</type>
      <sscc>00000379461100000007</sscc>
      <location>4260210630688</location>
      <device>VISTALINK.004</device>
      <date>2017-04-25</date>
      <time>01:22:20</time>
      <gmtOffset>+02:00</gmtOffset>
      <actorId>155081</actorId>
    </transaction>
    <order>
      <orderNumber>3794611</orderNumber>
    </order>
  </item>
</scope>

with a URI like this(all documents has a similar structure):

/transactions/2017-04-25_01-22-20_3794611_00000379461100000007_CI.xml

Now i created a template with the following structure:

xquery version "1.0-ml";
import module namespace tde = "http://marklogic.com/xdmp/tde" 
        at "/MarkLogic/tde.xqy";

let $transactions :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <context>/transactions</context>
  <rows>
    <row>
      <schema-name>main</schema-name>
      <view-name>transactions</view-name>
      <columns>
        <column>
          <name>type</name>
          <scalar-type>string</scalar-type>
          <val>type</val>
        </column>
    </columns>
    </row>
  </rows>
</template>
return tde:template-insert("Transactions.xml", $transactions)

I also to change the context to:

<context>item</context>

and /item

It does not return any error so i think the result will be fine

When I execute the following statement in the SQL console it returns an empty result:

select * from transactions;

When I validate the above template it returns the folowing result:

<map:map xmlns:map="http://marklogic.com/xdmp/map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<map:entry key="valid">
<map:value xsi:type="xs:boolean">false</map:value>
</map:entry>
<map:entry key="error">
<map:value xsi:type="xs:string">TDE-INVALIDTEMPLATENODE</map:value>
</map:entry>
<map:entry key="message">
<map:value xsi:type="xs:string">TDE-INVALIDTEMPLATENODE: Invalid extraction template node: /tde:template/tde:rows/text()</map:value>
</map:entry>
</map:map>

So the error by validating is :

Invalid extraction template node: /tde:template/tde:rows/text()
Invalid extraction template node: 

/tde:template/tde:rows/text()

Does any one know how I can fix this?


Solution

  • The problem is in your context. You have specified <context>item</context> but based on your sample document item is a child of scope. Therefore your template should look like this:

    xquery version "1.0-ml";
    import module namespace tde = "http://marklogic.com/xdmp/tde" at "/MarkLogic/tde.xqy";
    
    let $transactions :=
    <template xmlns="http://marklogic.com/xdmp/tde">
      <context>/scope/item/transaction</context>
      <rows>
        <row>
          <schema-name>main</schema-name>
          <view-name>transactions</view-name>
          <columns>
            <column>
              <name>type</name>
              <scalar-type>string</scalar-type>
              <val>type</val>
            </column>
        </columns>
        </row>
      </rows>
    </template>
    return tde:template-insert("Transactions.xml", $transactions)
    

    So what are we doing here? We are specifying the context to be /scope/item/transaction because the column type that you've specified in your row definition is under these elements. Loading this template will allow you to run the SQL statement SELECT * FROM transactions;