XSLT不仅输出标签文本

时间:2013-05-23 17:44:42

标签: xml xslt namespaces

我看过这个问题和我的问题一样: XSL Conversion XML->XML outputs only text?

但是我声明了一个默认命名空间,标签仍然没有被创建,我只是得到一个文本块。

这是我的XSLT的开始(它很大,所以我不会发布该批次)

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

    <xsl:template match="/x">
        <PatientData>
            <xsl:value-of select="x:Patientdata"/>
            <Versionnumber>
                <xsl:value-of select="x:Patientdata/Versionnumber"/>
            </Versionnumber>
            <Patient>
                <xsl:value-of select="x:Patientdata/Patient"/>
                <PatientCharacterstics>
                    <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics"/>
                    <patientCode>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/patientCode"/>
                    </patientCode>
                    <identifier>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/identifier"/>
                    </identifier>
                    <sex>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/sex"/>
                    </sex>
                    <dateOfBirth>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/dateOfBirth"/>
                    </dateOfBirth>
                    <DebutOfSymptoms>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/DebutOfSymptoms"/>
                    </DebutOfSymptoms>

我得到的只是一个巨大的文本块作为输出,而不是一个单独的标签。

编辑:根据要求提供一些示例输入XML,它是一个精简版本来说明,基本上xslt只是重新排列xml文件元素的顺序:

<Patientdata>
<Versionnumber>1</Versionnumber>
<Patient>
   <PatientCharacteristics>
      <dateOfBirth>1900-01-01</dateOfBirth>
      <patientCode>1</patientCode>
      <DebutOfSymptoms>1935-01-01</DebutOfSymptoms>
      <sex>1</sex>
      <identifier>7705</identifier>
   </PatientCharacteristics>
</Patient>
<Patient>
   <PatientCharacteristics>
      <dateOfBirth>1919-01-01</dateOfBirth>
      <patientCode>3</patientCode>
      <DebutOfSymptoms>1925-01-01</DebutOfSymptoms>
      <sex>2</sex>
      <identifier>7405</identifier>
   </PatientCharacteristics>
</Patient>
</Patientdata>

编辑2:我已经把它缩回了它的裸组件

XSLT:

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

    <xsl:template match="/">
        <PatientData>
            <xsl:value-of select="x:Patientdata"/>
            <Versionnumber>
                <xsl:value-of select="x:Patientdata/x:Versionnumber"/>
            </Versionnumber>
            <Patient>
                <xsl:value-of select="x:Patientdata/x:Patient"/>
                <PatientCharacterstics>
                    <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics"/>
                    <patientCode>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/patientCode"/>
                    </patientCode>
                    <identifier>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/identifier"/>
                    </identifier>
                    <sex>
                        <xsl:value-of select="x:Patientdata/x:Patient/x:PatientCharacteristics/x:sex"/>
                    </sex>
                    <dateOfBirth>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/dateOfBirth"/>
                    </dateOfBirth>
                    <DebutOfSymptoms>
                        <xsl:value-of select="x:Patientdata/Patient/PatientCharacteristics/DebutOfSymptoms"/>
                    </DebutOfSymptoms>

                </PatientCharacterstics>
            </Patient>
        </PatientData>
    </xsl:template>
</xsl:stylesheet>

这是我的XML

<?xml version="1.0"?>
<Patientdata>
<Versionnumber>1</Versionnumber>
<Patient>
   <PatientCharacteristics>
      <dateOfBirth>1900-01-01</dateOfBirth>
      <patientCode>1</patientCode>
      <DebutOfSymptoms>1935-01-01</DebutOfSymptoms>
      <sex>1</sex>
      <identifier>7705</identifier>
   </PatientCharacteristics>
</Patient>
<Patient>
   <PatientCharacteristics>
      <dateOfBirth>1919-01-01</dateOfBirth>
      <patientCode>3</patientCode>
      <DebutOfSymptoms>1925-01-01</DebutOfSymptoms>
      <sex>2</sex>
      <identifier>7405</identifier>
   </PatientCharacteristics>
</Patient>
</Patientdata>

这是输出:

<?xml version='1.0' ?>
<PatientData xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Versionnumber/>
<Patient>
<PatientCharacterstics>
<patientCode/>
<identifier/>
<sex/>
<dateOfBirth/>
<DebutOfSymptoms/>
</PatientCharacterstics>
</Patient>
</PatientData>

当输出应该是:

<?xml version="1.0"?>
<Patientdata>
<Versionnumber>1</Versionnumber>
<Patient>
   <PatientCharacteristics>
      <patientCode>1</patientCode>
      <identifier>7705</identifier>
      <sex>1</sex>
      <dateOfBirth>1900-01-01</dateOfBirth>
      <DebutOfSymptoms>1935-01-01</DebutOfSymptoms>
   </PatientCharacteristics>
</Patient>
<Patient>
   <PatientCharacteristics>
      <patientCode>3</patientCode>
      <identifier>7405</identifier>
      <dateOfBirth>1919-01-01</dateOfBirth>     
      <sex>2</sex>
      <DebutOfSymptoms>1925-01-01</DebutOfSymptoms>
   </PatientCharacteristics>
</Patient>
</Patientdata>

1 个答案:

答案 0 :(得分:1)

如果源XML数据具有默认名称空间声明,如

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

那么你的问题是你的模板试图匹配没有命名空间的x元素。您需要开始标记

<xsl:template match="/x:x">

但是,如果您认为模板正在执行的是应用默认命名空间,并且XML数据的根元素是Patientdata而不是x,那么您就会产生误解。您的模板应该只匹配根元素

<xsl:template match="/">

另请注意,在XPath表达式中的每一步上都需要名称空间前缀,例如

<xsl:value-of select="x:Patientdata/x:Patient/x:PatientCharacteristics/x:sex"/>

<强>更新

现在您已经展示了更多数据,我可以更好地理解您想要的内容。您声明了默认命名空间,xmlns:x命名空间声明以及匹配/x的模板的声明都是红色鲱鱼,并且您似乎根本不需要任何特殊的命名空间。 / p>

我想知道你的变换产生的输出可能没有看得太远,因为你的变换中有几个像<xsl:value-of select="x:Patientdata"/>这样的元素,这些元素是多余的并且导致输入的所有文本后代要复制到输出的元素。剩下的信息也在那里,但页面上有几行。

如果我删除了x命名空间prefx声明及其用法,以及那些不必要的value-of元素,那么您的转换工作正常。我还添加了一个output元素来启用输出缩进,使其看起来不错。

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <PatientData>
      <Versionnumber>
        <xsl:value-of select="Patientdata/Versionnumber"/>
      </Versionnumber>
      <Patient>
        <PatientCharacterstics>
          <patientCode>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/patientCode"/>
          </patientCode>
          <identifier>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/identifier"/>
          </identifier>
          <sex>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/sex"/>
          </sex>
          <dateOfBirth>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/dateOfBirth"/>
          </dateOfBirth>
          <DebutOfSymptoms>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/DebutOfSymptoms"/>
          </DebutOfSymptoms>

        </PatientCharacterstics>
      </Patient>
    </PatientData>
  </xsl:template>
</xsl:stylesheet>

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <PatientData>
      <Versionnumber>
        <xsl:value-of select="Patientdata/Versionnumber"/>
      </Versionnumber>
      <Patient>
        <PatientCharacterstics>
          <patientCode>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/patientCode"/>
          </patientCode>
          <identifier>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/identifier"/>
          </identifier>
          <sex>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/sex"/>
          </sex>
          <dateOfBirth>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/dateOfBirth"/>
          </dateOfBirth>
          <DebutOfSymptoms>
            <xsl:value-of select="Patientdata/Patient/PatientCharacteristics/DebutOfSymptoms"/>
          </DebutOfSymptoms>

        </PatientCharacterstics>
      </Patient>
    </PatientData>
  </xsl:template>

</xsl:stylesheet>

产生此输出

<?xml version="1.0" encoding="utf-8"?>
<PatientData>
   <Versionnumber>1</Versionnumber>
   <Patient>
      <PatientCharacterstics>
         <patientCode>1</patientCode>
         <identifier>7705</identifier>
         <sex>1</sex>
         <dateOfBirth>1900-01-01</dateOfBirth>
         <DebutOfSymptoms>1935-01-01</DebutOfSymptoms>
      </PatientCharacterstics>
   </Patient>
</PatientData>

更新2

XSLT实际上是一种声明性语言,虽然它有许多程序元素,如for-eachif,但最好使用模板来定义源代码的方式待处理。

我意识到你已经减少了变换,我所能看到你要做的就是重新排序每个PatientCharacterstics元素中的元素。这个模板将为您做到这一点。

第一个模板是通用复制模板,它匹配所有节点并通过复制开始标记,处理任何子节点和复制结束标记来处理它们。第二个模板是一个与要更改的元素匹配的特殊模板 - PatientCharacteristics - 通过以相同方式复制标记进行处理,但按照所需的特定顺序处理子项。

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="PatientCharacteristics">
    <xsl:copy>
      <xsl:apply-templates select="patientCode"/>
      <xsl:apply-templates select="identifier"/>
      <xsl:apply-templates select="sex"/>
      <xsl:apply-templates select="dateOfBirth"/>
      <xsl:apply-templates select="DebutOfSymptoms"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<?xml version="1.0" encoding="utf-8"?>
<Patientdata>
   <Versionnumber>1</Versionnumber>
   <Patient>
      <PatientCharacteristics>
         <patientCode>1</patientCode>
         <identifier>7705</identifier>
         <sex>1</sex>
         <dateOfBirth>1900-01-01</dateOfBirth>
         <DebutOfSymptoms>1935-01-01</DebutOfSymptoms>
      </PatientCharacteristics>
   </Patient>
   <Patient>
      <PatientCharacteristics>
         <patientCode>3</patientCode>
         <identifier>7405</identifier>
         <sex>2</sex>
         <dateOfBirth>1919-01-01</dateOfBirth>
         <DebutOfSymptoms>1925-01-01</DebutOfSymptoms>
      </PatientCharacteristics>
   </Patient>
</Patientdata>