Dela via


Läsa och skriva XML-data med hjälp av spark-xml biblioteket

Viktigt!

Den här dokumentationen har dragits tillbaka och kanske inte uppdateras. De produkter, tjänster eller tekniker som nämns i innehållet är inte officiellt godkända eller testade av Databricks.

Alternativt är stöd för internt XML-filformat tillgängligt i offentlig förhandsversion. Se Läsa och skriva XML-filer.

Den här artikeln beskriver hur du läser och skriver en XML-fil som en Apache Spark-datakälla.

Krav

  1. spark-xml Skapa biblioteket som ett Maven-bibliotek. För Maven-koordinaten anger du:

    • Databricks Runtime 7.x och senare: com.databricks:spark-xml_2.12:<release>

    Se spark-xmlVersioner för den senaste utgåvan av <release>.

  2. Installera biblioteket i ett kluster.

Exempel

I exemplet i det här avsnittet används XML-filen böcker .

  1. Hämta xml-filen för böcker:

    $ wget https://github.com/databricks/spark-xml/raw/master/src/test/resources/books.xml
    
  2. Ladda upp filen till DBFS.

Läsa och skriva XML-data

SQL

/*Infer schema*/

CREATE TABLE books
USING xml
OPTIONS (path "dbfs:/books.xml", rowTag "book")

/*Specify column names and types*/

CREATE TABLE books (author string, description string, genre string, _id string, price double, publish_date string, title string)
USING xml
OPTIONS (path "dbfs:/books.xml", rowTag "book")

Scala

// Infer schema

import com.databricks.spark.xml._ // Add the DataFrame.read.xml() method

val df = spark.read
  .option("rowTag", "book")
  .xml("dbfs:/books.xml")

val selectedData = df.select("author", "_id")
selectedData.write
  .option("rootTag", "books")
  .option("rowTag", "book")
  .xml("dbfs:/newbooks.xml")

// Specify schema

import org.apache.spark.sql.types.{StructType, StructField, StringType, DoubleType}

val customSchema = StructType(Array(
  StructField("_id", StringType, nullable = true),
  StructField("author", StringType, nullable = true),
  StructField("description", StringType, nullable = true),
  StructField("genre", StringType, nullable = true),
  StructField("price", DoubleType, nullable = true),
  StructField("publish_date", StringType, nullable = true),
  StructField("title", StringType, nullable = true)))

val df = spark.read
  .option("rowTag", "book")
  .schema(customSchema)
  .xml("books.xml")

val selectedData = df.select("author", "_id")
selectedData.write
  .option("rootTag", "books")
  .option("rowTag", "book")
  .xml("dbfs:/newbooks.xml")

R

# Infer schema

library(SparkR)

sparkR.session("local[4]", sparkPackages = c("com.databricks:spark-xml_2.12:<release>"))

df <- read.df("dbfs:/books.xml", source = "xml", rowTag = "book")

# Default `rootTag` and `rowTag`
write.df(df, "dbfs:/newbooks.xml", "xml")

# Specify schema

customSchema <- structType(
  structField("_id", "string"),
  structField("author", "string"),
  structField("description", "string"),
  structField("genre", "string"),
  structField("price", "double"),
  structField("publish_date", "string"),
  structField("title", "string"))

df <- read.df("dbfs:/books.xml", source = "xml", schema = customSchema, rowTag = "book")

# In this case, `rootTag` is set to "ROWS" and `rowTag` is set to "ROW".
write.df(df, "dbfs:/newbooks.xml", "xml", "overwrite")

Alternativ

  • Läsa
    • path: Plats för XML-filer. Accepterar standard Hadoop-uttryck för globbing.
    • rowTag: Radtaggen som ska betraktas som en rad. I den här XML-koden <books><book><book>...</books>blir booktill exempel värdet . Standard är ROW.
    • samplingRatio: Samplingsförhållande för slutsatsdragningsschema (0,0 ~ 1). Standard är 1. Möjliga typer är StructType, ArrayType, StringType, LongType, DoubleType, BooleanType, TimestampType och NullType, såvida du inte anger ett schema.
    • excludeAttribute: Om du vill exkludera attribut i element. Standardinställningen är falsk.
    • nullValue: Det värde som ska behandlas som ett null värde. Standard är "".
    • mode: Metoden för att hantera skadade poster. Standard är PERMISSIVE.
      • PERMISSIVE:
        • När den påträffar en skadad post anger den alla fält till null och placerar den felaktiga strängen i ett nytt fält som konfigurerats av columnNameOfCorruptRecord.
        • När det stöter på ett fält med fel datatyp anger du det felande fältet till null.
      • DROPMALFORMED: ignorerar skadade poster.
      • FAILFAST: utlöser ett undantag när det identifierar skadade poster.
    • inferSchema: om trueförsöker du härleda en lämplig typ för varje resulterande DataFrame-kolumn, till exempel en boolesk, numerisk eller datumtyp. Om falseär alla resulterande kolumner av strängtyp. Standard är true.
    • columnNameOfCorruptRecord: Namnet på det nya fältet där felaktiga strängar lagras. Standard är _corrupt_record.
    • attributePrefix: Prefixet för attribut så att attribut och element kan särskiljas. Det här är prefixet för fältnamn. Standard är _.
    • valueTag: Taggen som används för värdet när det finns attribut i ett element som inte har några underordnade element. Standard är _VALUE.
    • charset: Standardvärdet är UTF-8 men kan anges till andra giltiga teckenuppsättningsnamn.
    • ignoreSurroundingSpaces: Huruvida blanksteg som omger värden ska ignoreras eller inte. Standardinställningen är falsk.
    • rowValidationXSDPath: Sökväg till en XSD-fil som används för att verifiera XML för varje rad. Rader som inte kan verifieras behandlas som parsningsfel som ovan. XSD påverkar inte det angivna eller härledda schemat. Om samma lokala sökväg inte redan visas på Spark-exekutorerna i klustret, bör XSD och andra filer den är beroende av läggas till på Spark-exekutorerna med SparkContext.addFile. I det här fallet, om du vill använda lokal XSD /foo/bar.xsd, anropar du addFile("/foo/bar.xsd") och skickar "bar.xsd" som rowValidationXSDPath.
  • Skriva
    • path: Plats för att skriva filer.
    • rowTag: Radtaggen som ska betraktas som en rad. I den här XML-koden <books><book><book>...</books>blir booktill exempel värdet . Standard är ROW.
    • rootTag: Rottaggen som ska behandlas som rot. I den här XML-koden <books><book><book>...</books>blir bookstill exempel värdet . Standard är ROWS.
    • nullValue: Värdet för att skriva null värde. Standard är strängen "null". När "null"skrivs inte attribut och element för fält.
    • attributePrefix: Prefixet för attribut för att särskilja attribut och element. Det här är prefixet för fältnamn. Standard är _.
    • valueTag: Taggen som används för värdet när det finns attribut i ett element som inte har några underordnade element. Standard är _VALUE.
    • compression: Komprimeringskodec som ska användas när du sparar till filen. Bör vara det fullständigt kvalificerade namnet på en klass som implementerar org.apache.hadoop.io.compress.CompressionCodec eller ett av skiftlägesokänsliga kortnamn (bzip2, gzip, lz4och snappy). Standardvärdet är ingen komprimering.

Stöder den förkortade namnanvändningen. Du kan använda xml i stället för com.databricks.spark.xml.

XSD-stöd

Du kan verifiera enskilda rader mot ett XSD-schema med hjälp av rowValidationXSDPath.

Du använder verktyget com.databricks.spark.xml.util.XSDToSchema för att extrahera ett Spark DataFrame-schema från vissa XSD-filer. Den stöder endast enkla, komplexa och sekvenstyper, endast grundläggande XSD-funktioner och är experimentella.

import com.databricks.spark.xml.util.XSDToSchema
import java.nio.file.Paths

val schema = XSDToSchema.read(Paths.get("/path/to/your.xsd"))
val df = spark.read.schema(schema)....xml(...)

Parsa kapslad XML

Även om den främst används för att konvertera en XML-fil till en DataFrame kan du också använda metoden from_xml för att parsa XML i en strängvärdeskolumn i en befintlig DataFrame och lägga till den som en ny kolumn med tolkade resultat som en struct med:

import com.databricks.spark.xml.functions.from_xml
import com.databricks.spark.xml.schema_of_xml
import spark.implicits._

val df = ... /// DataFrame with XML in column 'payload'
val payloadSchema = schema_of_xml(df.select("payload").as[String])
val parsed = df.withColumn("parsed", from_xml($"payload", payloadSchema))

Kommentar

  • mode:
    • Om värdet är inställt på PERMISSIVE, vilket är standardinställningen, är parsningsläget i stället DROPMALFORMED. Om du inkluderar en kolumn i schemat för from_xml som matchar columnNameOfCorruptRecord, utdata i PERMISSIVE-läge felaktiga poster till den kolumnen i den resulterande strukturen.
    • Om värdet är inställt på DROPMALFORMEDresulterar XML-värden som inte parsas korrekt i ett null värde för kolumnen. Inga rader tas bort.
  • from_xml konverterar matriser med strängar som innehåller XML till matriser med parsade structs. Använd schema_of_xml_array i stället.
  • from_xml_string är ett alternativ för användning i UDF:er som körs på en sträng direkt i stället för en kolumn.

Konverteringsregler

På grund av strukturella skillnader mellan DataFrames och XML finns det vissa konverteringsregler från XML-data till DataFrame och från DataFrame till XML-data. Du kan inaktivera hanteringsattribut med alternativet excludeAttribute.

Konvertera XML till DataFrame

  • Attribut: Attribut konverteras som fält med prefixet som anges i attributePrefix alternativet. Om attributePrefix är _, dokumentet

    <one myOneAttrib="AAAA">
        <two>two</two>
        <three>three</three>
    </one>
    

    skapar schemat:

    root
    |-- _myOneAttrib: string (nullable = true)
    |-- two: string (nullable = true)
    |-- three: string (nullable = true)
    
  • Om ett element har attribut men inga underordnade element placeras attributvärdet i ett separat fält som anges i valueTag alternativet. Om valueTag är _VALUE, dokumentet

    <one>
        <two myTwoAttrib="BBBBB">two</two>
        <three>three</three>
    </one>
    

    skapar schemat:

    root
    |-- two: struct (nullable = true)
    |    |-- _VALUE: string (nullable = true)
    |    |-- _myTwoAttrib: string (nullable = true)
    |-- three: string (nullable = true)
    

Konvertera DataFrame till XML

När du skriver en XML-fil från en DataFrame med ett fält ArrayType, där dess element är ArrayType, kommer det att finnas ett ytterligare kapslat fält för elementet. Detta skulle inte inträffa vid läsning och skrivning av XML-data, utan när du skriver ut en DataFrame läst från andra källor. Därför har läsning och skrivning av XML-filer samma struktur, men när man skriver en DataFrame som lästs in från andra källor kan den ha en annan struktur.

En dataram med schemat:

 |-- a: array (nullable = true)
 |    |-- element: array (containsNull = true)
 |    |    |-- element: string (containsNull = true)

och data:

+------------------------------------+
|                                   a|
+------------------------------------+
|[WrappedArray(aa), WrappedArray(bb)]|
+------------------------------------+

skapar XML-filen:

<a>
  <item>aa</item>
</a>
<a>
  <item>bb</item>
</a>