如何修复丑陋的XQuery输出?

时间:2011-05-01 18:44:18

标签: xml xsd xquery

这是我的XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="student.xsl"?>
<Students xmlns="www.example.com"     
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="www.example.com student.xsd">
<Student>
    <SSN>622-12-5748</SSN>
    <Name>
        <First-Name>Alexander</First-Name>
        <Last-Name>Mart</Last-Name>
    </Name>
    <Age>26</Age>
    <Institution>UCSF</Institution>
    <Email>Alexander@yahoo.com</Email>
</Student>
</Students>

我有这个XQuery:

xquery version "1.0";

declare namespace xsd = "http://www.w3.org/2001/XMLSchema";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
declare default element namespace "http://www.example.com";

for $s in doc("student.xml")/Students/Student
let $firstName := $s/First-Name
let $lastName := $s/Last-Name
let $email := $s/Email
order by $lastName ascending
return 
<row>
    <first-name> { $firstName } </first-name>
    <last-name> { $lastName } </last-name>
    <email> { $email } </email>     
</row>

我得到的输出是:

<row xmlns="http://www.example.com">
    <first-name>
        <First-Name xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   >Alexander</First-Name>
    </first-name>
    <last-name>
        <Last-Name xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  >Mart</Last-Name>
    </last-name>
    <email>
        <Email xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              >Alexander@yahoo.com</Email>
    </email>
</row>

我看到的所有例子都输出如下内容:

<row>
    <first-name>Alexander</first-name>
    <last-name>Mart</last-name>
    <email>Alexander@yahoo.com</email>
</row>

如何像这样格式化我的输出?

另外,为什么我得到这个

<First-Name xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
我的搜索结果中的

标记,而不只是<first-name>?有没有办法摆脱它?我将declare default element namespace "http://www.example.com";添加到顶部附近,因为如果没有它我无法让我的XQuery工作。但如果没有在我的结果中显示,那将是非常好的。

3 个答案:

答案 0 :(得分:3)

使用

declare namespace  x = "http://www.example.com";  

for $s in /x:Students/x:Student
  let $firstName := $s/x:First-Name/text()
    let $lastName := $s/x:Last-Name/text() 
      let $email := $s/x:Email/text() 
  order by $lastName ascending 
     return  
      <row>     
        <first-name> { $firstName } </first-name>     
        <last-name> { $lastName } </last-name>     
        <email> { $email } </email>      
      </row> 

当它应用于以下XML文档时(您没有提供XML文档!!!):

<Students  xmlns="http://www.example.com">
  <Student>
    <First-Name>A</First-Name>
    <Last-Name>Z</Last-Name>
    <Email>A.Z@T.com</Email>
  </Student>
</Students>

生成了想要的结果

<row>
   <first-name>A</first-name>
   <last-name>Z</last-name>
   <email>A.Z@T.com</email>
</row>

解释:文字结果元素(row等)位于默认元素名称空间中。解决方案不是使用默认元素名称空间声明。

答案 1 :(得分:0)

XQuery 1.0没有标准方法来请求缩进(或其他格式化)结果。许多XQuery实现都有自己的机制。例如,如果您从命令行使用Saxon,则可以使用选项!indent = yes。我不知道XMLSpy提供了哪些选项。

有一个XQuery 1.0选项“声明边界空间保留”,它会导致查询中的空格被复制到输出中;这可能会产生你需要的效果,但根据我的经验,它也会产生不良影响。

答案 2 :(得分:0)

首先,您的确切查询不应该产生该输出。您必须使用它(因为输入上的默认命名空间声明):

declare namespace xsd = "http://www.w3.org/2001/XMLSchema";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
declare namespace x = "www.example.com";
declare default element namespace "http://www.example.com";
for $s in /x:Students/x:Student
let $firstName := $s/x:Name/x:First-Name
let $lastName := $s/x:Name/x:Last-Name
let $email := $s/x:Email
order by $lastName ascending
return
<row>
     <first-name> { $firstName } </first-name>
     <last-name> { $lastName } </last-name>
     <email> { $email } </email>
</row>

确实输出了:

<row xmlns="http://www.example.com">
    <first-name>
        <First-Name xmlns="www.example.com"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   >Alexander</First-Name>
    </first-name>
    <last-name>
        <Last-Name xmlns="www.example.com" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  >Mart</Last-Name>
    </last-name>
    <email>
        <Email xmlns="www.example.com"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              >Alexander@yahoo.com</Email>
    </email>
</row>

为什么?:因为您的序列构造函数{ $firstName }输出由$firstName引用的节点实例而不是其字符串值。那应该是:

declare namespace x = "www.example.com";
declare default element namespace "http://www.example.com";
for $s in /x:Students/x:Student
let $firstName := $s/x:Name/x:First-Name
let $lastName := $s/x:Name/x:Last-Name
let $email := $s/x:Email
order by $lastName ascending
return
<row>
     <first-name> { $firstName/string() } </first-name>
     <last-name> { string($lastName) } </last-name>
     <email> { normalize-space($email) } </email>
</row>

输出:

<row xmlns="http://www.example.com">
    <first-name>Alexander</first-name>
    <last-name>Mart</last-name>
    <email>Alexander@yahoo.com</email>
</row>